Share via


How to call COM+ remotely with anonymous user

 

The purpose of this tutorial is to give you an idea on how to call the COM+ server remotely. I’m not going to go into the depths of COM+ details or how to develop COM+, this tutorial is designed to show 3 ways on how to call COM+ server with VC++.

Environment: Windows 2000 for server side, Windows XP for client side

Step 1: Setting COM+ security on server side

If the client and server are in same ___domain, we only need to grant “Access” and “Launch” permissions to Domain Users. Now we hope to call the COM+ component out of ___domain, this could be anonymous access.

1. Configure the COM+ security

1) Uncheck "Enforce access checks for this application"

2) Check "Perform access checks only at the process level......"

3) "Authentication level for calls: None"

4) "Impersonation level: Anonymous"

Call_COM_01

2. Enable “guest” account for windows.

Call_COM_02

Step 2: Call the COM+ remotely

Method 1: Export proxy from server side and then install it on client side

1. On the server side, in “Component Services”, right click your COM+ application and select “Export…”

2. In the “COM Application Export Wizard”, select type as “Application proxy”, it will produce a *.msi file.

3. Install the *.msi file on the client side

Then, you can call this COM+ just as installed on localhost. Here’s the sample code.

void main(void)

{

// Declare and HRESULT and a pointer to the Simple_ATL interface

HRESULT hr;

ISimpleClass *IS = NULL;

// Now we will intilize COM

hr = CoInitialize(0);

// Use the SUCCEDED macro and see if we can get a pointer to

// the interface

if(SUCCEEDED(hr))

{

hr = CoCreateInstance( CLSID_SimpleClass, NULL, CLSCTX_REMOTE_SERVER, IID_ISimpleClass, (void**) &IS);

if(SUCCEEDED(hr))

{

BSTR ReturnValue;

hr = IS->HelloWorld(&ReturnValue);

char* pValue=_com_util::ConvertBSTRToString(ReturnValue);

cout << pValue << endl;

hr = IS->Release();

}

else

{

printf("CreateInstance Error!Error Code:%x\n",hr);

}

}

// Uninitialize COM

CoUninitialize();

}

Method 2: Register the COM+ dll on client side with “RemoteServername”

1. Register the dll as DCOM: regsvr32 <yourcom.dl>

2. Search the DCOM component in registry, find the CLSID of your COM dll

3. Under the CLSID , Create a Key named "AppID", and set the value as same as the value of CLSID

4. Delete the value of CLSID\InprocServer32

5. Add the AppID of step 3 under HKEY_CLASSES_ROOT\AppID

6. Add "RemoteServerName" to the to HKEY_CLASSES_ROOT\AppID\{YourAppID}, the value is the remote server's name

Here’s the example of the registry key settings.

---------------------------------------------------------------------------

 Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\AppID\{23F55D14-50A5-45E1-B8EA-FBE3E789BA97}]
@="TestCom.SimpleClass"
"RemoteServerName"="zx-win2k02"

[HKEY_CLASSES_ROOT\CLSID\{23F55D14-50A5-45E1-B8EA-FBE3E789BA97}]
@="SimpleClass Class"
"AppID"="{23F55D14-50A5-45E1-B8EA-FBE3E789BA97}"

[HKEY_CLASSES_ROOT\CLSID\{23F55D14-50A5-45E1-B8EA-FBE3E789BA97}\InprocServer32]
@=""
"ThreadingModel"="Apartment"

-------------------------------------------------------------

The source code is as same as Method 1.

Method 3: Call the COM+ remotely with CoCreateInstanceEx

 

1. Register the dll as DCOM: regsvr32 <yourcom.dl>

2. Write the source code with CoCreateInstanceEx, and specify the remote server name in source code. Here’s the example.

void main(void)

{

      HRESULT hr;

      ISimpleClass *pI=NULL;

     

      COSERVERINFO sin,*sinptr;

      MULTI_QI mqi;

      mqi.pIID=&IID_ISimpleClass;

      mqi.hr=0;

      mqi.pItf=0;

      COAUTHINFO authInfo;

      authInfo.dwAuthnSvc = RPC_C_AUTHN_NONE;

      authInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;

……

      sin.dwReserved1=0;

      sin.dwReserved2=0;

      sin .pwszName=L"zx-win2k02";//define the remote server name here

      sin.pAuthInfo=&authInfo;

      sinptr=&sin;

     

      hr=CoInitialize(0);

      if(SUCCEEDED(hr))

      {

           

            hr=CoCreateInstanceEx(CLSID_SimpleClass,

                                          NULL,

                                          CLSCTX_REMOTE_SERVER,

                                          sinptr,

                                          1,

                                          &mqi

                                          );

            if(SUCCEEDED(hr))

            {

            pI=(ISimpleClass*)mqi.pItf;

            BSTR bsReturnValue;

     

            pI->HelloWorld(&bsReturnValue);

     

            char* pValue=_com_util::ConvertBSTRToString(bsReturnValue);

            printf("%s\n",pValue);

            delete pValue;

     

            }

            else

            {

                  printf("CreateInstance Error!Error Code:%x\n",hr);

            }

      }

References

 

Client/Server connection using DCOM, with anonymous access: https://www.codeproject.com/KB/COM/clientserverwithdcom.aspx

DCOM Architecture: https://msdn.microsoft.com/en-us/library/ms809311.aspx

COM+ (Component Services) : https://msdn.microsoft.com/en-us/library/ms685978(VS.85).aspx

CoCreateInstanceEx Function: https://msdn.microsoft.com/en-us/library/ms680701(VS.85).aspx

CoCreateInstance Function: https://msdn.microsoft.com/en-us/library/ms686615(VS.85).aspx

 

Regards,

Zhixing Lv

Comments