1

I'm trying to create out-of-proc com server in some exe file and a client, which will access to functions through proxy\stub mechanism. I have my .idl file:

[
    object,
    uuid(eaa27f4f-ad6b-4a52-90f3-6028507751a1),
    dual,
    nonextensible,
    helpstring("IConfig Interface"),
    pointer_default(unique)
]
interface IInterractionInterface : IDispatch
{
    [id(1), helpstring("Testing function")] HRESULT Test([in] long param);
};


[
    uuid(6fde5037-3034-4ae1-8aa7-2ad45e5716e4),
    version(1.0),
    helpstring("Some lib")
]
library SomeLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");

    [
        uuid(86feabe4-a0a7-45b5-bcd4-f4f7085d6b1f),
        helpstring("Some lib")
    ]
    coclass Interraction
    {
        [default] interface IInterractionInterface;
    };
}

I am generated using midl compiler _p.c, _i.c files, created proxy\stub dll using .def:

LIBRARY        proxy_stub.dll
DESCRIPTION    'generic proxy/stub DLL'
EXPORTS        DllGetClassObject      @1 PRIVATE
               DllCanUnloadNow        @2 PRIVATE
               DllRegisterServer      @4 PRIVATE
               DllUnregisterServer    @5 PRIVATE

Then i am registered this dll using regsrv32, and in win registry i have this: enter image description here

In my server i am created factory:

CoRegisterClassObject(CLSID_InterractionInterfaceFactory, (IClassFactory*) &factory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &regID);

And it waits for client calls. In client i am calling my factory using CreateInstance:

result = CoGetClassObject(CLSID_InterractionInterfaceFactory, CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (void**)&factory);

if (S_OK == result)
{
    IInterractionInterface* iface = NULL;

    result = factory->CreateInstance(NULL, IID_InterractionInterface, (void**)&iface);
    if (S_OK == result)
    {

    }
}

And client receives null iface and result is E_UNEXPECTED, but in factory it creates successfuly and i am returning S_OK from Factory::CreateInstance(). I can't understand is PS mechanism using my .dll or not? Maybe i forgot some steps? Why my object can't pass through process borders?

Edit: I've tried to replace the client code and now it is:

result = CoCreateInstance(CLSID_InterractionInterfaceFactory, NULL, CLSCTX_LOCAL_SERVER, IID_InterractionInterface, (void**)&iface);
iface->Test(1);

And when i am trying to call Test(1) it throws an error, that this is pure virtual function. And in factory in CreateInstance i am receiving requirement of Unkonown interface.

fryme
  • 251
  • 4
  • 15
  • Using a proxy/stub requires a registry key entry in `HCKR\Interfaces`, the ProxyStubClsId32 value must be set to the CLSID for the proxy. It is not clear if this was done properly. E_UNEXPECTED is however not the kind of error you'd expect when you have registration trouble, you'd get E_NOINTERFACE instead. Try using SysInternals' ProcMon, you might get a better hint about what's going wrong. Some kind of DLL loading problem, maybe. – Hans Passant Aug 02 '13 at 12:24
  • No this path on screenshot is HKEY_CLASSES_TOOR\Wow6432Node\CLSID\{GUID}. It is not right? – fryme Aug 02 '13 at 12:34
  • It is right, just not the only one. You also need *extra* keys, one each in `HKCR\Interfaces` for every interface that's implemented by the server. That's how COM figures out what server needs to be used when it is asked to marshal an interface. You can easily see this back in ProcMon, recommended. – Hans Passant Aug 02 '13 at 12:43
  • I found using ProcMon that my server trying to read (from registry) CLSID of Factory object and can't, because it is not registered. And there is no any registry read when it trying to receive instance of interface. I can't understand how it must work. I need to send some data from one process to another. I need a factory-createInstance scheme or it will be enough only instance? But how then i will send already created instance from server to client? – fryme Aug 02 '13 at 13:38
  • That sounds accurate. Your client code should use CoCreateInstance() to create an "Interraction" object. – Hans Passant Aug 02 '13 at 13:47
  • But it was already created in the server process. – fryme Aug 02 '13 at 13:54
  • No, you created the class factory in the server. Ready to create an "Interraction" object when the client wants one. – Hans Passant Aug 02 '13 at 14:10
  • And i need to register my factory in system registry and in .idl file? – fryme Aug 02 '13 at 14:23
  • No you don't. You register the factory with CoRegisterClassObject(). Like you did. – Hans Passant Aug 02 '13 at 14:32

1 Answers1

2

If you want to use proxy/stub DLL, define the interface outside of the library block. Only stuff defined outside of library goes into the code generated for proxy/stub DLL. Stuff defined, or referenced, inside library block goes into the generated type library. A typical IDL file defines interfaces outside of library, then mentions them inside, in coclass blocks; this way interface definitions end up in both proxy/stub and TLB, for maximum flexibility.

Your interface is automation compatible (well, almost; change the parameter type from int to long). In this case, you may prefer to use so called "universal" marshalling, based on a type library. Simply register the MIDL-generated TLB file with regtlib tool or programmatically with LoadTypeLibEx, and you would have marshaling support in place.

Igor Tandetnik
  • 45,980
  • 4
  • 51
  • 75
  • I am updated my question. I am defined interface outside of the library block in .idl file. Then i am registered with regtlib, as you say and made some edits in client code (look to the bottom of the post). And now i have an error that function, that i am trying to call is pure virtual. I think that's because it requesting Unknown interface. – fryme Aug 05 '13 at 07:11
  • Why did you make that change to the client code? Does your class factory object actually implement `IInterractionInterface`? This would be unusual: typically, a class factory implements `IClassFactory`, and its `CreateInstance` implementation creates a new object which, in turn, implements the desired interface. – Igor Tandetnik Aug 05 '13 at 12:52