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: http://www.codeproject.com/KB/COM/clientserverwithdcom.aspx


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


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


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


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


 


Regards,


 


Zhixing Lv


 

Skip to main content