COM in please, how to make out-of-process COM server work? (fixed)

1

I have difficult to make an out-of-process COM server work properly. My steps are

1. define idl (classic.idl)

import "objidlbase.idl";
[
    uuid(CF86E2E0-B12D-4C6A-9C5A-D7AA65101E91),
]
coclass CClassic
{
   [default] interface IClassic;
}
[
  object,
  uuid(CF86E2E0-B12D-4C6A-9C5A-D7AA65101E90),
  pointer_default(unique)
]
interface IClassic : IUnknown
{
    HRESULT Hello();
}

2. generate the proxy/stub files

midl /nologo /out classic /I"D:\EWDK\Program Files\Windows Kits\10\Include\10.0.19041.0\um" /I"D:\EWDK\Program Files\Windows Kits\10\Include\10.0.19041.0\shared" classic.idl

3. implement the interface (comobj.cpp)

#include <atlbase.h>
#include <atlcom.h>
#include "classic/classic.h"

CComModule _Module;
extern "C" CLSID CLSID_CClassic;

struct Toast : CComObjectRoot,CComCoClass<Toast,&CLSID_CClassic>,IClassic
{
  DECLARE_REGISTRY(CLSID_CClassic,"Toaster.1.0","Toaster","Toast Server",THREADFLAGS_BOTH);
  DECLARE_CLASSFACTORY();
  DECLARE_OBJECT_DESCRIPTION("Toast Server");

  BEGIN_COM_MAP(Toast)
    COM_INTERFACE_ENTRY(IClassic)
  END_COM_MAP();
 
  HRESULT STDMETHODCALLTYPE Hello( void)
  {
    printf("Hello\n");
    return S_OK;
  }
};

OBJECT_ENTRY_AUTO(CLSID_CClassic,Toast);

4. write the out-of-process module (comexe.cpp)

#include <atlbase.h>
#include <atlcom.h>
struct MyModule : CAtlExeModuleT<MyModule>
{
};

MyModule mod;

int main(int argc, char *args[])
{
  mod.WinMain(SW_HIDE);
}

5. compile the module

cl /nologo /EHsc comexe.cpp comobj.cpp classic/classic_i.c /link /debug

6. compile the proxy/stub

cl /nologo /EHsc /DREGISTER_PROXY_DLL /DPROXY_CLSID=CLSID_CClassic classic/classic_p.c classic/classic_i.c classic/dlldata.c /link /dll /out:comproxy.dll /export:DllGetClassObject /export:DllCanUnloadNow /export:DllRegisterServer /export:DllUnregisterServer /export:GetProxyDllInfo rpcrt4.lib

7. register server (with sysadmin account)

comexe /RegServer

8. register proxy/stub (with sysadmin account)

regsvr32 comproxy.dll

7 and 8 are on the same machine

9. write a test client (test.cpp)

#include <Unknwn.h>
#include <stdio.h>
#include "classic\classic.h"
#pragma comment(lib, "ole32")

extern "C" CLSID CLSID_CClassic;

int main(int argc, char *args[])
{
  CoInitialize(nullptr);
  IClassic *ifc = nullptr;
  HRESULT hr;
  if(argc<2) return 1;
  switch(args[1][0])
  {
    case 'I':
    case 'i':
      hr = CoCreateInstance(CLSID_CClassic,nullptr,CLSCTX_INPROC_SERVER,IID_IClassic,(void**)&ifc);
      break;
    case 'O':
    case 'o':
      hr = CoCreateInstance(CLSID_CClassic,nullptr,CLSCTX_LOCAL_SERVER,IID_IClassic,(void**)&ifc);
    default:
      ;
  }  
  printf("0x%x\n",hr);
}

10. compile the test

cl /nologo /std:c++latest /EHsc test.cpp classic/classic_i.c /link /debug

11. run the test

on the same machine

test O
0x80004002
test I
0x80004002

Please help. Many thanks!!!

Update

Finally, I found in the step 6 I should use PROXY_CLSID_IS instead of PROXY_CLSID to define the CLSID for the proxy/stub which must different from CLSID_CClassic, that is:

cl /nologo /EHsc /DREGISTER_PROXY_DLL /DPROXY_CLSID_IS={0xCF86E2E0,0xB12D,0x4C6A,{0x9C,0x5A,0xD7,0xAA,0x65,0x10,0x1E,0x93}} classic/classic_p.c classic/classic_i.c classic/dlldata.c /link /dll /out:comproxy.dll /export:DllGetClassObject /export:DllCanUnloadNow /export:DllRegisterServer /export:DllUnregisterServer /export:GetProxyDllInfo rpcrt4.lib

and this time

test O
0x0

and test I still failed, but I think it is not the right way to call an out-of-process server.

com
atl
asked on Stack Overflow Aug 9, 2020 by yushang • edited Aug 10, 2020 by yushang

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0