user1503961
user1503961

Reputation: 11

How to load COM dll modules and expose their interfaces as out of proccess servers

I have an out of process server based on the ATL Service VC++2010 Template. Now I wont to extend his COM Interface by dynamically loading additional dlls that contain its own COM Classes. The dll to load is based on ATL dll VC++2010 Template, containing a simple ATL-object "IMModule". I changed the corresponding .rgs file to connect the class from the dll to the EXE server by adding a LocalServer section and the server's AppID as follows:

HKCR
{
  NoRemove CLSID
  {
    ForceRemove {59276614-A811-4D27-B131-514656E643D3} = s 'IMModule Class'
    {
      ForceRemove Programmable
      LocalServer32 = s 'path to the service exe'
      {
    val ServerExecutable = s 'path to the service exe'
      }
      TypeLib = s '{250685C7-CBD3-4FF8-A3A6-2AF668794CFC}'
      Version = s '1.0'
      val AppID = s '{7EFD508A-53C6-4EA0-B21A-D29277B86CBC}'
    }
  }
}

In a dll init() method called by the service after loading the dll I call CoRegisterClassObject to register the IMModule class object. But im not sure how to obtain the IUnknown interface pointer (second parameter to CoRegisterClassObject ). I tried the following:

CIMModule::_ClassFactoryCreatorClass* pClassFak = 
    new CIMModule::_ClassFactoryCreatorClass;
IUnknown* pUnk;
HRESULT hr =
pClassFak->CreateInstance(CIMModule::_ClassFactoryCreatorClass::CreateInstance, 
                            IID_IIMModule, (LPVOID*)&pUnk);

But the call to CreateInstance fails with E_NOINTERFACE. So, how to register my IMModule class implemented inside a dll to be available for COM clients from my out of process server?

Upvotes: 0

Views: 1096

Answers (2)

user1503961
user1503961

Reputation: 11

With the help from Roman.R I get the behavior that I need. I can't say thank you enough, @roman-r. I will precisely describe what I did, so maybe someone can retrace the steps and give me some response.

First I created an ATL based Windows service (named UmbrellaService). Inside UmbrellaService I added a simple ATL-Object named Control and added the method:

 FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);

Thats all with the VC++ Wizard. Then I fixed the Control.rgs file by adding:

 val AppID = s '%APPID%'

Why has VC++ still such bugs after 17 years of evolution? (See CoCreateInstance does not start or connect to ATL COM service) Then I created an ATL-dll Project, named MyModule, with a "Module" simple ATL-Object inside. The Module class has a method

testMethod (LONG a, LONG b, LONG* sum)"

The MyModule dll is registered as a in-proc server. Furthermore the dll has some classes that makes the dll a plugin as I need it.

In the PreMessageLoop method of the UmbrellaService the MyModule dll will be loaded with LoadLibrary and through GetProcAddress the address of a factory creation method is obtained. The factory creation method returns a plugin-dependent FactoryClass that acts as a plugin entry point. This is my COM-independent plugin mechanism.

Now to export the module interface from the plugin dll through the UmbrellaService interface I did the following: On the FactoryClass I add the method:

IDispatch* getInterface();

In getInterface method I call

CoCreateInstance(__uuidof(Module), NULL , CLSCTX_INPROC_SERVER , __uuidof(IDispatch), (VOID**) &pDispatch); 

and return the obtained IDispatch interface. The FactoryClass::getInterface method is called inside the Control::FindMeAnInterface method of the UmbrellaService after comparing the name passed to FindMeAnInterface with the name provided by the FactoryClass. FindMeAnInterface returns the then obtained IDispatch pointer to the client.

On the client side I import the tlb file from the UmbrellaService and the tlb from the apropriate plugin dll. I call testMethod as follows:

IControlPtr pControl(__uuidof(Control));
_bstr_t moduleName("Module");
IDispatchPtr moduleDisp = pControl->FindMeAnInterface(moduleName);
IModulePtr pModule(moduleDisp );
LONG res = pModule->testMethod(42,23);

This all works indeed, but I am not sure if this is the way to do it. Did I miss something about reference counting? Will the plugin DLL be loaded two times? First time through my plugin mechanism and second time through CoCreateInstance? Something else I should note?

Thanks for your help!

Upvotes: 1

The Original Android
The Original Android

Reputation: 6215

I could not find my code so far. But I did check one of my favorite websites, The Code Project. It used to be popular especially with older technologies like COM (yes, it is). I hope you're already convinced that you have to use COM instead of new WFC or another technology.

Please check good documentation and sample code @ ATL COM EXE doc. I believe I used this web page as a start of my past project.

Good luck and have fun.

Upvotes: 0

Related Questions