Persistent DCOM Interface pointer in an ISAPI DLL made with Delphi 2006

You have an ISAPI DLL and like to perform outgoing COM/DCOM calls ? You either can setup the connection to the remote Server in every call, which might not be the most efficient way, or you can create the Interface pointer once and use it in every call. In the following I describe, how this works.
 
image002
Before you start coding in the DLL, there are a few steps you need to take care of. Because you use DCOM, you have to configure the Identity of the Website inside the IIS. You can do this by opening the Properties window of the virtual directory and change to the Tab sheet “Directory Security”. There you click in the group box “Authentication and access control” the Button Edit and enter select a User with sufficient rights on the Box, which runs the remote DCOM Server.
 
You also need to take care, that the User which runs the virtual directory and this means this User runs the ISPAI DLL, is allowed to “use” the DCOM Server on the remote machine. So open up DCOMCNFG on the remote machine and configure the Application there so that the entered User has Launch, Activation and Access Permissions for the DCOM Server Application.
 
After this security issues, you need to take care, that the COM Server is registered on the machine, which runs the IIS 6.0. Also take care, that the User which runs the ISAPI DLL has access file permissions to the folder, in which the .tlb/.exe files are you used to register the COM Server.
 
Now you can start using the DCOM Interface pointer in the Code of the ISAPI DLL.  To have the pointer “global” you need to declare a pointer variable in the interface section of the implementation unit of the Webservice (MyWebserviceimpl.pas).
 
 
var
  MyServerStream: Pointer;
 
implementation
 
This pointer is used to hold the Interface pointer and pass it between the threads in every call.
 
In the method, where you like to use the interface pointer you declare a variable of the real type
 
var
  ILocalMyServer: IMyServer;
begin
 

Now you can create a connection to the remote Object, if not already done:

 
if MyServerStream = nil then
  begin
    // Create Stream if it is not there already
    ILocalMyServer:=
    (CreateRemoteComObject('SOME_COMPUTER’, CLASS_MyServer) as IMyServer);
    //Pass the Interface pointer to the Stream
    OleCheck(CoMarshalInterThreadInterfaceInStream(IID_IMyServer, ILocalMyServer,
    IStream(MyServerStream)));
  end;
 
And call a Interface method on the Remote Server:
 
//Get the Interface Pointer from the Stream
OleCheck(CoGetInterfaceAndReleaseStream(IStream(MyServerStream), IID_IMyServer, ILocalMyServer));
// Stream is invalid, make this clear
MyServerStream:= nil;
//Make the COM Call on the remote Server
ILocalMyServer.SomeFunction(SomeVar1, SomeVar2);
//Pass the Interface pointer to the Stream
OleCheck(CoMarshalInterThreadInterfaceInStream(IID_IMyServer, ILocalMyServer, IStream(MyServerStream)));
 
References:
-          http://msdn2.microsoft.com/en-us/library/ms691421.aspx
-          http://www.microsoft.com/germany/msdn/library/components/AchtLektionenZumThemaCOM.mspx?mfr=true
-          http://groups.google.de/group/borland.public.delphi.oleautomation/browse_thread/thread/d698c5f4488d9411/ebbd31f28389dc6f?lnk=st&q=%22Interface+not+supported%22+ISAPI+Delphi&rnum=25&hl=de#ebbd31f28389dc6f
-          http://groups.google.de/group/borland.public.delphi.internet/browse_thread/thread/3ef0aaae05a84af9/db2a9b25c0bfe63f?lnk=st&q=%22global+data%22+ISAPI+Delphi&rnum=3&hl=de#db2a9b25c0bfe63f