Pluggable
protocol
There is not much difference between
the pluggable namespacehandler and a pluggable protocolhandler of
the following type:
myhttp://www.euromind.com/iedelphi
Declare the name of your new protocol in RegisterNameSpace:
procedure
TForm1.FormCreate(Sender: TObject);
begin
CoGetClassObject(Class_Protocol, CLSCTX_SERVER, nil, IClassFactory,
Factory);
CoInternetGetSession(0, InternetSession, 0);
InternetSession.RegisterNameSpace(Factory, Class_Protocol, 'myhttp',
0, nil, 0);
end;
However, in the namespacehandler demo
you had the functionality of the default http-protocol to build on.
When you register a new protocol, you don't automatically have this,
but must build it from scratch and it is not always an easy job.
To make the work easier you can aggregate the
default http-protocol. Use TAggregatedObject or just use TComObject
(which support aggregating in D4 & D5). Override function
Initialize and create an instance of the original http-protocol:
procedure TProtocol.Initialize;
begin
inherited;
if FDefaultProtocol = nil then
CoCreateInstance(Class_HttpProtocol, Iunknown(Self),
CLSCTX_INPROC_SERVER,
IUnknown, FDefaultProtocol);
end;
Class_HttpProtocol is not included in
urlmon.pas, but you can find it in WIN32 SDK:
Class_HttpProtocol: TGUID =
'{79eac9e2-baf9-11ce-8c82-00aa004ba90b}';
Use this instance of http-protocol as the inner object and your
implementation of IInternetProtocol as the outer object. Now you can
deligate most of the work to the original protocol. In each
function you can call the http-protocol before or after your
modifications, e.g:
function TProtocol.Read(pv:
Pointer; cb: ULONG; out cbRead: ULONG): HResult;
begin
//Make your modifications here ///
Result := (FDefaultProtocol as IInternetprotocol).Read(pv, cb,
cbread);
//Make your modifications here ///
end;
In this way the new protocol is just a simple
wrapper around the default http-protocol.
To create it as a permanent pluggable protocol, put
your protocol in a DLL and add a key named "myhttp" (or
what you choose as name for your protocol) to the registry under
HKEY_CLASSES_ROOT\PROTOCOLS\Handler. Under the new key,
HKEY_CLASSSES_ROOT\PROTOCOLS\Handler\myhttp, the string value, CLSID,
must be assigned the CLSID of your protocol handler.
The following demo demonstrates how to aggregate the
default http-protocol in a new protocol. Notice the implementation
of IInternetProtocolSink and IInternetBindInfo. This is a simple
trick, so all calls from the http-protocol to the transaction
handler can be captured, by replacing IOProtSink and IOBindInfo with
self when function "start" is deligated to the
original http-protocol:
Result := (FDefaultProtocol as
IInternetprotocol).Start(szUrl, self, self, grfPI,
dwReserved);
AppHelper.pas is included to make debugging
easier.The demo is only tested in D5 but should work also in D4.