Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Emergecy:How to convert application from COM to DCOM???

404 views
Skip to first unread message

Will Zhang

unread,
Nov 4, 1998, 3:00:00 AM11/4/98
to
My compliction is based on COM, but Now ,I want to conver it to DCOM, so I
used OLE-COM Object viewer(VC tools), There under all-object I find my
object and change the remote machine name under activation tab to the
REMOTE dns name.
and I also delete the pathname under implementation tab,then I copy my
server file (dll file)to remote machine and use regsvr32 to regester it.But
,on client ,when I use CoCreateInstance function the returning code always
tell me the class is not registered or the Server execution failed. who can
help me to solve the problem. (COM have no problem)

Thanks very very much in advance!!!

mar...@tyga.com

unread,
Nov 20, 1998, 3:00:00 AM11/20/98
to
In article <utCR864B#GA....@uppssnewspub05.moswest.msn.net>,
I found this article very helpful.

Making the Transition from COM to DCOM

Using COM to create an object-oriented distributed computer system can be
quite effective in many ways. Up until the release of Windows NT 4.0 however,
COM components residing in out of process (out-proc) servers could
communicate only with clients running on the same computer. With the release
of Windows NT 4.0, Microsoft introduced DCOM (Distributed Component Object
Model), which allows out-proc servers to reside on computers remote to its
clients. In addition, Microsoft provided a DCOM upgrade for Windows 95 as
well. Consequently there could be a mix and match of clients and servers
running on NT and 95.

Since COM has been around for a while, there are probably many developers
(myself included) who have built systems based on COM and would like to
redesign their systems by making some local servers remote in order to reap
the true benefits a distributed computer system such as utilizing the
collective processing power of the network.

In this article I will show you how to use the Distributed COM Configuration
(often referred to as DCOM-Config) utility that ships with Windows NT 4.0 to
make a local server remote-able without modifying a single line of code in
either the client or server. Then, by making minor changes to the client, I
will show you how to change the client so that it can connect to a remote
server without having to refer to entries in the Windows Registry.

Making a local server remote

To make an out-proc server remote-able, you should first start by identifying
the computer on which you want your server process to run. Next, copy the
server and its dependent files to the designated computer. Then register the
server by calling the server name followed by a /RegServer flag similar to the
example below.

Myserver.exe /RegServer If the server contains custom interfaces and the
proxy/stub code was compiled in a separate dll, you must register the dll by
using the RegSvr32 utility similar to the example below. RegSrv32
MyServerPS.dll As I mentioned previously, Windows NT 4.0 ships with the
DCOM-Config utility. The actual file name is DComCnfg.exe. It is normally
located in the SYSTEM32 subdirectory under the Windows NT operating system
directory. When DCOM-Config is launched, a three-tab dialog appears. I will
discuss only the Applications tab. The other two deal with authentication
levels and default security. These are issues that cannot be disregarded in a
production environment; however, in order to remain focused on making a
out-proc server accessible to remote clients, I will not discuss what these
tabs do per se, but I will cover some of the DCOM security features later on.
The Applications tab contains a list of registered components that reside in
out-proc servers. You should find the components that reside in the out-proc
server that you just registered. To make the make the components in a server
accessible to clients on remote computers:

Modify the properties of the selected component by double-clicking on the
selected component or by clicking on the Properties button. This will launch a
properties dialog with four tabs labeled General, Location, Security, and
Identity.

Click on the Location tab.

Check the checkbox labeled "Run application on this computer".

Make sure the remaining checkboxes are unchecked.

By default, no one has access to the server; therefore, click on the Security
tab.

Click on the radio button labeled "Use custom access permissions".

Click on the Edit button. A Registry Value Permissions dialog will appear.

Give users access permission by clicking the Add button. An Add Users and
Groups dialog will appear. Adding users is self-explanatory; nevertheless, in
a development environment, security should be less restrictive until the
server has been fully tested. A user could have access privileges to a
component but may or may not have rights to launch the server process in
which the components they have access to reside. Since we are not too
concerned about security at this point, give launching permissions to the
same users to which you assigned access permissions by clicking on the radio
button labeled "User custom launch permissions".

Follow this by clicking on the Edit button. The same dialog used in Custom
Access permissions will appear. Select the same users.

Now select the Identity tab, which determines the identity of the client
process interacting with components in the server process. There are four
ways a client process can be identified: an Interactive user, Launching user,
specific user, and System Account user. If you select the radio button
labeled the Interactive user, DCOM will allow the client process to adapt the
identity of the user currently logged on to the computer where the server
process is running. If no one is logged on, the client will be unable to
connect with a server process.

If you select the radio button labeled the Launching user, DCOM will retain
the identity of the client process that launched the server process. Unlike
the Interactive user identity, the Launching user will automatically launch a
server if one is not already running for that particular user whether or not
a user is logged on locally at the computer where the server process resides.
However, if another client process with a different user account attempts to
interact with components in the running server process, DCOM will
automatically launch a separate server process.

If you select the radio button labeled This user, you must provide a valid
user for the server process to impersonate when performing tasks for a given
client process.

You can select System Account user only if your server process is a Windows NT
service. If so, the server process will impersonate a system account provided
by the operating system or added by an Administrator.

Let's assume the server process in not a service, and the intention is to
allow users to have access to the server whether or not anyone is logged on
the computer where the server lives. In cases like these, select the radio
button labeled the Launching user.


Click the OK button to accept all changes and exit DCOM-Config.

The server is now properly registered and configured for DCOM. Now let's
configure the clients that will remotely communicate with components in the
server.
Converting a COM client to DCOM using DCOM-Config

Converting a COM client to a DCOM client is done by simply launching the DCOM-
Config utility and setting the server location.


Similar to configuring the server, you must identify the components the server
provides, and set the location by invoking the Properties dialog and selecting
the Location tab.

Check the checkbox labeled, "Run Application on the following computer:".
This will enable the corresponding edit control and browse button. You can
either type in the name of the computer or browse the network for available
computers.

Make sure the other checkboxes are not checked, and click the OK button to
save and exit the Properties dialog followed by clicking the OK button to
exit DCOM- Config.

Although the server will be remote to the client, it still has to be
registered on the client's computer in order for the server components to
appear on the Applications tab in DCOM-Config. The easiest way to accomplish
this is to follow the initial steps used to configure a DCOM server, which is
to copy the server to the computer and run it with a /RegServer flag. Don't
forget: If the server contains custom interfaces and the proxy/stub code was
compiled in a separate dll, you must copy the dll to client's computer and
register it by using the RegSvr32 utility similar to what was previously
illustrated in the server configuration. Both the client and the server side
require the proxy/stub code for successful cross-process communication to
take place. Now that the client configuration is complete, you should be able
to the launch the client application which, through the magic of DCOM, will
connect with a server on a remote computer. Speaking of magic, how does it
all work?

Understanding the magic

Simply put, DCOM-Config updates the Windows Registry. For COM, the Windows
Registry is a database of CLSID mappings to server applications. The CLSID
uniquely identifies a class factory designed to create instances of a
specific component exclusively in a server process and return a pointer to an
interface supported by the component to the requesting client. When most
clients attempt to perform this task they call CoGetClassObject directly or
indirectly through another COM API function. CoGetClassObject will locate the
class factory associated with the CLSID. If it is unable to find it active in
memory, it refers to the CLSID mapping to the server in the Windows Registry.
It then launches the COM server, whose immediate responsibility is to make
all its class factories for each unique component available to COM. Be aware
that implementation differs from in-proc to out-proc servers, but the concept
is the same.


HRESULT __stdcall CoGetClassObject(
const CLSID& rclsid, //CLSID associated with the class
factory
DWORD dwClsContext, //Context for running executable code
COSERVERINFO * pServerInfo, //Reserved for DCOM
const IID& riid, //Reference to the identifier of
the interface (Typically this
//is IID_IClassFactory or IID_IClassFactory2)
void** ppv //Indirect pointer to the interface
);

Once the client has a pointer, the IClassFactory it can follow it with a call
to IClassFactory::CreateInstance, which will construct an instance for the
component in the server process and return a pointer to an interface
requested by the client. HRESULT IClassFactory::CreateInstance( IUnknown *
pUnkOuter, //Points to out IUnknown if the component is an aggregate. const
IID& riid, //Reference to the identifier of the interface requested void **
ppvObject //Indirect pointer to the interface );


A code extract of a COM client would then look similar to the following:
IBabyFactory* pBabyFactory; // Baby object factory
IVocal* pVocal; // Pointer to a Baby's IVocal interface

// Get the baby class factory
CoGetClassObject(CLSID_Baby, CLSCTX_LOCAL_SERVER, NULL,
IID_IClassFactory, (void**)&pBabyFactory);

// Construct a baby and return a pointer to its IVocal interface
pBabyFactory->CreateInstance(NULL, IID_IVocal, (void**)&pVocal);

// Release the baby factory interface. If there are no outstanding
// references to interfaces supported by the factory, it will be
// destroyed.
pBabyFactory->Release();

// Make the baby scream.
pVocal->Scream();

// Make the baby laugh
pVocal->Laugh();

// Release the IVocal interface. If there are no outstanding // references
to interfaces supported by the Baby, it will be // destroyed.
pVocal->Release(); The use of the Windows Registry has not changed much
between COM and DCOM. Microsoft cleverly uses the registry to keep DCOM
backward-compatible with COM. DCOM-Config updates the Windows Registry by
adding a new AppID entry in three places. In no particular order, first there
is new the named value (not a subkey), AppID added to the CLSID subkey. AppID
is also GUID (Global Unique Identifier) just like the CLSID. Next, the AppID
value is also added as a subkey under the "AppID" key. This AppID subkey,
will contained the named value, RemoteServerName. Its contents will be the
location of the remote server as entered in DCOM-Config. Lastly, the server
file name (e.g. myserver.exe) is entered as subkey under the "AppID" key. It
also contains the named value, AppID. Analyzing the Windows Registry can be
overwhelming. The diagram below, which resembles a similar visual
representation of what you would see if you ran the Registry Editor
(regedt32.exe), clearly illustrates what I've described.

HKEY_CLASSES_ROOT
|
***
---AppID
***
-- {6E75BB91-89B1-11D0-8DA0-00A024CEEAA8} --- RemoteServerName
"AnotherComputer"
***
--myserver.exe Ğ AppID
"{6E75BB91-89B1-11D0-8DA0-00A024CEEAA8}"
--CLSID
***
-- {6E75BB91-89B1-11D0-8DA0-00A024CEEAA8} --- AppID
"{6E75BB91-89B1-11D0-8DA0-
00A024CEEAA8}"
***


In the DCOM release, many of the COM API function implementations have been
updated to take advantage of the AppID without changing function signatures.
Therefore, it is transparent to the client whether the out-proc server is
local or remote. For example, let's look at the case of the CoGetClassObject
function, when the execution context is set to CLSCTX_LOCAL_SERVER and the
COSERVERINFO* parameter (refer to the function prototype illustrated earlier)
is set to NULL. Using the CLSID pass in by reference, CoGetClassObject will
locate the CLSID in the Windows Registry. Assuming there is an AppID value,
it will use the AppID to locate the RemoteServerName. If found, it will
attempt to locate a reference to the class factory on the remote computer.
Depending on the client's security privileges, it may launch the server
application on the remote computer if a reference to the desired class
factory is unavailable. Similar to COM, the server is then responsible for
making all of its class factories readily available. At this point
CoGetClassObject obtains a pointer to the class factory interface associated
with its CLSID and returns it to the requesting client. Everything is
wonderful in the world since with the assistance of DCOM-Config, and the
transparent usage of the DCOM API functions, an existing COM client and
server can be converted to DCOM. However, going forward, all new development
should be done using DCOM. As an introduction to DCOM, I will do a
walk-through on creating a DCOM client.

Creating a DCOM client without using the DCOM-Config utility

Along with the release of DCOM, Microsoft has added new functions and updated
the implementation of functions previously provided in COM. To ensure a DCOM
client will compile, one of the following preprocessor symbols must be defined
in your project:

_WIN32_DCOM or _WIN32_WINNT >= 0x400 If you are using VC++/MFC to build the
client, I suggest placing the definition within the stdafx.h header file.
This does not, however, guarantee that a DCOM application will run on a given
computer. The computer's operating system should be either Windows NT 4.0 or
Windows 95 with the DCOM upgrade installed. Needless to say, newer versions
of these operating systems as they are released will support DCOM. There are
a couple of ways to verify this fact. You can check the Windows Registry to
see if DCOM is enabled by using WIN32 API registry functions (Hint: The
answer is in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Ole =>
EnableDCOM = ?). Next, you can get the address of a known DCOM API function
located in the OLE32.DLL. If found, you know the DCOM library is available.
Building a DCOM client is not much different than a COM client. The following
code extract is an enhancement to the code used to illustrate a COM client
earlier.

IVocal* pVocal; // Pointer to baby's IVocal interface
IMotor* pMotor; // Pointer to baby's IMotor interface
COSERVERINFO serverInfo; // DCOM Server Information structure
MULTI_QI interfaces[2]; // Array of MUTI_QI structures of size 2

// Initialize structure to 0.
memset(&serverInfo, 0, sizeof(COSERVERINFO));

// Set server info name to remote server.
serverInfo.pwszName = L"AnotherComputer"

// Assign elements of MUTI_QI structure
interfaces[0].pIID = &IID_IVocal; // [in] Baby's IVocal Interface ID.
interfaces[0].pItf = NULL; // [out] Pointer to baby's IVocal
interface
interfaces[0].hr = 0; // [out] HRESULT
interfaces[1].pIID = &IID_IMotor; // [in] Baby's IMotor Interface ID
interfaces[1].pItf = NULL; // [out] Pointer to baby's IMotor
interface
interfaces[1].hr = 0; // [out] HRESULT

// Construct a baby and fill in the array of MULT_QI structures with pointers
to interfaces that correspond
// with the IID's stored in the pIID structure element
HRESULT hr = CoCreateInstanceEx(CLSID_ Baby, NULL, CLSCTX_SERVER, &serverInfo,
2, interfaces);

if (SUCCEEDED(hr))
{
pVocal = (IVocal*)interfaces[0].pItf;
pMotor = (IMotorl*)interfaces[1].pItf;

pVocal->Scream(); // Make the baby scream.
pMotor->Crawl(); // Make the baby crawl.
pVocal->Laugh(); // Make the baby laugh.
pMotor->Stand(); // Make the baby stand up.

// Release the IVocal and IMotor interfaces. If there are no outstanding //
references to interfaces supported by the Baby, it will be // destroyed.
pVocal->Release(); pMotor->Release(); } As I mentioned previously, most
clients use CoGetClassObject directly or indirectly through another COM API
function to obtain a pointer to a class factory interface. In the code above,
I use CoCreateInstanceEx which is a DCOM version of the helper function
CoCreateInstance. Similar to its COM predecessor, this function internally
calls CoGetClassObject to obtain a pointer to a specific class factory
interface as determined by the CLSID. It then creates an instance of the
component in the server process, and obtains multiple interface pointers to
the requesting client. Notice that the COSERVERINFO structure contains the
remote server name. The address of this structure is now passed to
CoCreateInstanceEx. With the execution context used to indicate an out-proc
server, CoCreateInstanceEx will internally call CoGetClassObject, which will
bypass the Windows Registry to obtain a pointer to class factory interface
located on the remote server as provided by the COSERVERINFO structure. Next,
Microsoft realized that any remote invocation can be costly including the
marshaling of interface pointers. Hence, CoCreateInstanceEx provides the
ability return multiple interfaces from the same component within one
invocation. To do so you must pass an array of MULTI_QI structures. The
MULTI_QI structure is defined as follows:

typedef struct _MULTI_QI {
const IID* pIID;
IUnknown * pItf;
HRESULT hr;
} MULTI_QI;

pIID is a pointer to an interface identifier supplied by the requesting
client. pItf is a pointer to the interface requested in pIID. It should be
set to NULL prior to passing the MULTI_QI structure to CoCreateInstanceEx. Hr
is the return value of the QueryInterface call made to satisfy the request
for the interface requested in pIID. It should be set to zero prior to
passing the MULTI_QI structure to CoCreateInstanceEx. From this point on, the
rest of the code is typical of all COM clients. Conclusion

Building a distributed computer system can effectively improve the computer
system infrastructure implemented at any organization, provided the decision-
makers agree on the correct architecture. DCOM makes it possible to turn a
design into a reality. DCOM is backward compatible with its COM predecessor.
Using the DCOM-Config utility makes it extremely easy to transform a self-
contained COM-based system into a distributed COM-based system without writing
a single line of code. Most importantly, the enhancements made to DCOM,
including the addition of new API functions, and changes to existing functions
remain in line with the COM specification; therefore, there is little to no
impact on a COM developer's approach to building a component-based
architecture.

POSTED 3/12/97 BY WS

Written by Linda Esralian on 3/25/97.

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

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

0 new messages