Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C++

DCOM D-Mystified: A DCOM Tutorial, Step 2

Rate me:
Please Sign up or sign in to vote.
4.79/5 (10 votes)
11 Aug 2000CPOL 238.9K   2.2K   55   20
We modify starter files, provided by the ATL COM AppWizard, to improve the user-friendliness of our server.

Introduction

Welcome to Step 2 of our DCOM tutorial. In this series, I will strip the mystique, the headache, and confusion from DCOM by giving you a comprehensive tutorial with a straightforward example. OK, no promises -- but I will give it a good try.

If you want to follow along with this tutorial and add code and use the Visual C++ Wizards as we go along, that's great. In fact, I very very highly recommend that, because otherwise this tutorial is a big waste of electronic ink (?). However, I follow along exactly with the tutorial myself, as I write it, and develop the code and use the Visual C++ wizards just as I say you should. The screenshots, in fact, are from my development of the files for each step! To download this already-developed code to compare with your own, simply click the 'Download the Step n Files - n KB" links at the top of each step. There's also an archive of the files for all the steps at the Questions and Answers page for this tutorial. I still recommend that you follow along with us as we go; this way, you can learn while you code. If you ever have problems along the way with this tutorial, feel free to:

A diagram of how our software will eventually work is shown in Figure 1. The client calls a method on the server, which then fires an event back to the client using a connection point. This connection point's event sink is implemented in the client (using MFC and ClassWizard!!!), and the client shows its user a message telling the user that the server said "Hello!":

Diagram of our DCOM client/server set-up.
Figure 1. Diagram of our DCOM client/server set-up.

Remember, our steps in developing the software in this tutorial are as follows:

  • Step 1: Create the server, HelloServ, using the ATL COM AppWizard.
  • Step 2: Modify the starter files provided by AppWizard.
  • Step 3: Use the New ATL Object Wizard to add a simple COM object, the HelloWorld object, to the server.
  • Step 4: Modify the IHelloWorld interface to include a SayHello() method.
  • Step 5: Add an event method, OnSayHello(), to the connection point source interface, DHelloWorldEvents.
  • Step 6: Build the server, and install it on the server computer.
  • Step 7: Create a MFC client, HelloCli, which calls the server and handles the connection point event sink.

We're currently on Step 2 of the tutorial, where we modify some things in the starter source code provided to us by the ATL COM AppWizard. We do this to:

  • Provide a user-friendly "Display Name" for this service;
  • Add code to initialize security properly.

Step 2: Modify the Starter Files Provided by AppWizard

To start, we need to provide Windows with a user-friendly name it can use to display this service to the user. This is called the "Display Name" of the service. AppWizard already set up and specified a "Service Name" for us: HelloServ. For the user's sake, let's come up with something which is easier to understand: Hello World Server. To do this, we'll add a m_szDisplayName member variable to the CServiceModule class, and a String Table entry to hold the display name. We do things this way so that it's easy for us to change the display name of the service to whatever we wish.

First, double-click on the CServiceModule icon in ClassView. This will jump you to where the CServiceModule class is declared, in STDAFX.H. We need to add a m_szDisplayName member variable to the class. Move the cursor to the // data members section, and add the code shown below in bold:

class CServiceModule : public CComModule
{
    ...

// data members
public:
    TCHAR    m_szDisplayName[256];        // display name of service
    TCHAR    m_szServiceName[256];

    ...
};
Listing 1. Adding the m_szDisplayName member variable to the CServiceModule class.

The next thing to do is to add an entry to the String Table, IDS_DISPLAY_NAME, to hold the display name we want to use. Figure 2, shown below, illustrates adding the String Table entry. To do this, complete these steps:

  1. Click the ResourceView tab.
  2. Double-click the String Table folder to open it.
  3. Double-click the String Table icon in the folder to open the String Table.
  4. Find the blank entry in the list, and double-click it. The Properties window appears, as in Figure 2, below.
  5. In the ID box, type IDS_DISPLAY_NAME.
  6. Press TAB to move to the Caption box, which contains what the IDS_DISPLAY_NAME symbol maps to in your code.
  7. In the Caption box, type Hello World Server, as shown in Figure 2.
  8. Press Enter. This saves the new String Table entry to the String Table.

Adding the IDS_DISPLAY_NAME entry to the String Table.
Figure 2. Adding the IDS_DISPLAY_NAME entry to the String Table.

On to the next part of Step 2. We have a member variable, m_szDisplayName, which we want to fill with the contents of the String Table entry IDS_DISPLAY_NAME. To do this, double-click the CServiceModule::Init() function in ClassView, and then add the line shown in bold:

inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, 
    UINT nServiceNameID, const GUID* plibid)
{
    ...

    LoadString(h, nServiceNameID, m_szServiceName,
                sizeof(m_szServiceName) / sizeof(TCHAR));

    LoadString(h, IDS_DISPLAY_NAME, m_szDisplayName,
                sizeof(m_szDisplayName) / sizeof(TCHAR));

    ...
}
Listing 2. Adding a LoadString() call to CServiceModule::Init().

Now we have made sure that the IDS_DISPLAY_NAME string gets loaded into the m_szDisplayName member variable of CServiceModule. The next thing to do is to change the call to CreateService() in the CServiceModule::Install() function. The call is shown in Listing 3 below in bold. The call is again shown in Listing 4, also below, but this time the argument which you need to replace is shown in bold:

inline BOOL CServiceModule::Install()
{
    ...

    SC_HANDLE hService = ::CreateService(
        hSCM, m_szServiceName, m_szServiceName,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);

    ...
}
Listing 3. The call to the Windows CreateService() function, as called by AppWizard.

Change the second passing of m_szServiceName to m_szDisplayName, as shown in Listing 4:

inline BOOL CServiceModule::Install()
{
    ...

    SC_HANDLE hService = ::CreateService(
        hSCM, m_szServiceName, m_szDisplayName,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);

    ...
}
Listing 4. Changing the second m_szServiceName to m_szDisplayName.

Finally, the last part of Step 2 is to initialize everything properly. Go to the place in the HELLOSERV.CPP file shown // PLACE THE CURSOR HERE comment in Listing 5:

#include "stdafx.h"
#include "resource.h"
#include < initguid.h >
#include "HelloServ.h"

#include "HelloServ_i.c"


#include < stdio.h >

CServiceModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()

// PLACE THE CURSOR HERE

LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
{
    ...
Listing 5. Where in the HELLOSERV.CPP file to place the cursor.

Add all of the following code at where I've just told you to place the cursor:

extern "C" BOOL WINAPI InitApplication()
{
    HRESULT hResult = CoInitialize(NULL);
        if (FAILED(hResult))
            return FALSE;        // failed to initialize COM

    // Turn security off so that everyone has access to us
    CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);

   // Initialization successful
   return TRUE;
}
Listing 6. Adding the InitApplication() function to the server. Next, we need to replace some of the code in CServiceModule::Run() with a call to the InitApplication() function which we added in Listing 6 above. Using ClassView, go to the CServiceModule::Run() function, and delete the code shown in bold:
void CServiceModule::Run()
{
    ...

    HRESULT hr = CoInitialize(NULL);
//  If you are running on NT 4.0 or higher you can use the following call
//  instead to make the EXE free threaded.
//  This means that calls come in on a random RPC thread
//  HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

    _ASSERTE(SUCCEEDED(hr));

    // This provides a NULL DACL which will allow access to everyone.
    CSecurityDescriptor sd;
    sd.InitializeFromThreadToken();
    hr = CoInitializeSecurity(sd, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    _ASSERTE(SUCCEEDED(hr));

    ...
}
Listing 7. Code to delete from the implementation of CServiceModule::Run().

Now replace what I told you to delete with the code shown in Listing 8 below. The code to add is shown in bold:

void CServiceModule::Run()
{
    ...

    HRESULT hr = S_OK;

    if (!InitApplication())
        return;

    ...
}
Listing 8. Code to add in order to replace what we've deleted.

Notes From the Rear

We've now completed Step 2 of this tutorial. We added a display name to help the user, and we fixed the security-initialization code for the service. Click Next to move on to the next step of this tutorial, Step 3, click Back to go back to Step 1 of this tutorial, or click the Questions and Answers button to jump to the Questions and Answers page! Good luck.

<< Back | Next >>

Questions and Answers

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
United States United States
Brian C. Hart, Ph.D., is a strategic engagement leader on a mission to leverage space technology to protect U.S. interests and assets against adversaries. Throughout Dr. Hart's career, he has enjoyed: Working closely with business executives to provide strategic direction and leadership, translating customer and competitive intelligence into compelling capture strategies and solutions, and mentoring teams to enhance individual and company capabilities while fostering an engaging and accountable environment, being involved in STEAM initiatives and education to develop greater awareness in the community, and serving the armed forces with the U.S. Navy and U.S. Army National Guard. He is excited to begin developing his career in Jacobs's Critical Mission Systems business unit, supporting NORAD and the U.S. Space Force.

Comments and Discussions

 
GeneralModify ACL Pin
rajendra@yahoo.com28-Sep-05 3:16
rajendra@yahoo.com28-Sep-05 3:16 
GeneralMake Sure and Configure DCOM on Windows XP Pro SP2 Pin
Brian C Hart26-Mar-05 9:02
professionalBrian C Hart26-Mar-05 9:02 
GeneralProblem !!! Pin
eddie_serban2-May-05 21:52
eddie_serban2-May-05 21:52 
Generalwin98 Pin
thides9-Mar-05 7:53
thides9-Mar-05 7:53 
GeneralRPC Server is Unavailable Pin
csdave210-May-04 21:40
csdave210-May-04 21:40 
GeneralWith Visual C++ this would be much easier Pin
Vagif Abilov13-Aug-02 21:45
professionalVagif Abilov13-Aug-02 21:45 
GeneralRe: With Visual C++ this would be much easier Pin
Trollslayer18-May-03 11:47
mentorTrollslayer18-May-03 11:47 
Generalsecurity Pin
Haresh2-May-02 21:39
Haresh2-May-02 21:39 
QuestionHaving a Question? Pin
Brian C Hart2-Jan-02 16:07
professionalBrian C Hart2-Jan-02 16:07 
GeneralUnable to call AfxConnectionAdvise Pin
9-Nov-00 20:24
suss9-Nov-00 20:24 
GeneralRe: Unable to call AfxConnectionAdvise Pin
Brian C Hart2-Jan-02 16:15
professionalBrian C Hart2-Jan-02 16:15 
GeneralRe: Unable to call AfxConnectionAdvise Pin
Alexandre R Oliveira20-Aug-02 7:14
Alexandre R Oliveira20-Aug-02 7:14 
GeneralRe: Unable to call AfxConnectionAdvise Pin
intensely_radioactive4-Sep-03 4:44
intensely_radioactive4-Sep-03 4:44 
GeneralRemoving code in step 2 Pin
Michael Groeger18-Sep-00 21:40
Michael Groeger18-Sep-00 21:40 
GeneralRe: Removing code in step 2 Pin
7-Feb-01 1:28
suss7-Feb-01 1:28 
GeneralRe: Removing code in step 2 Pin
Brian C Hart26-Feb-01 13:39
professionalBrian C Hart26-Feb-01 13:39 
But dividing my tutorial into more steps makes sense only if I am selling this to a magazine...on The Code Project, this is free! Poke tongue | ;-P

brian
GeneralRe: Removing code in step 2 Pin
Brian C Hart26-Feb-01 13:41
professionalBrian C Hart26-Feb-01 13:41 
GeneralRe: Removing code in step 2 Pin
20-Apr-01 5:06
suss20-Apr-01 5:06 
GeneralRe: Removing code in step 2 Pin
22-May-01 12:10
suss22-May-01 12:10 
GeneralRe: Removing code in step 2 Pin
Brian C Hart6-Jul-01 20:44
professionalBrian C Hart6-Jul-01 20:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.