Windows NT Systems Programming: Spring 2000
[ Home | Syllabus | Course Notes | Assignments | Search]
Distributed Objects
Different Models of Distribution
- Object state is copied to many clients
- Objects state exists on Server, but can be accessed remotely
Proxy Object on Client
- Object state is divided between machines.
Issues
- Locating the Object
- Data Typing
- Data Representation
- Persistance
- Security
- Reliability and Availability
- Load Balancing
CORBA
Common Object Request Broker Architecture (specification)
- Define Object interface in IDL (Interface Description Language) -
NOT RPC one
- Produces STUB on client and SKELETON on server
- Use CORBA API to BIND to an object (object REFERENCE) - somewhat
like a context handle in RPC)
- Supports Exceptions
- Object Factories to create objects instances (Basic Object
Adaptor)
- Has both Static and Dynamic Invocation
- Server can be started as needed
Java Distributed Objects
- Distributes bytecode
- Use Java Sockets
- RMI (Remote Method INvocation)
- Uses Java serialization
- extend Remote interface
- Implement Interface
- Naming using URLs
COM
- Microsoft's binary standard
- Accesses Object through interfaces (local or remote)
- Objects must be registered in local system registry
- Indentified by IIDs and CLSIDs
- Static and dynamic invocation (IDISPATCH)
- Can start server as needed
- Supports naming, persistence, object lifetime.
Historical Perspective
- ClipBoard. finished product - not editable, not updated
- DDE (Dynamic Data Exchange): linked copied data back to original
so changes could be reflected in copy.
- OLE 1.0 (16 bit)
- OLE 2.0 (16 bit)
- OCX
- 32bit OLE
- ActiveX
OLE 1.0
- Presentation Data (GDI Metafile)
- Class Information: application for editing the data
- DATA: raw data (enbedded) or file name of raw data (linked)
- Used DDE as interprocess communications
- Compound Document
- Could Edit Objects embedded in compound documents
OLE 2.0
- Based on a Component Object Model (COM): binary standard for
talking to an object
- error reporting
- memory management (structured storage for compound documents)
- in place activiation
- drag and drop (Universal Data Transfer)
- in-place editing
- Automation
OLE Controls (OCXs)
- DLLs containing controls with methods and properties (Visual
Basic 4)
- Load OCX into a container
- Container and OCX talked using COM interfaces
- OCX COM interface exported methods and properties
- Container COM interface exported event handlers from OCX events
- Spawned a OCX mini industry
32 bit OLE/COM/ActiveX
- Built on top of RPC
- Cross Platform
- NetWork OLE = DCOM
- ActiveX Controls = OCX
- DCOM being ported to other platforms
COM basics
- Binary Specification (Language independent)
Uses an array of function pointers to access methods
- What an object is
- What it can do
- What is its lifetime
- Groups functions into interfaces which can be named and
registered
- COM Class implements one or more interfaces
- COM objects are instantiated from COM classes
- Every COM object must inplement the interface IUnknown
Key to object lifetime management
IUnknown
HRESULT QueryInterface(REFIID iid, void** ppvObject);
ULONG AddRef(void);
ULONG Release(void);
- Object lifetime is managed through a reference count
- AddRef increases and Release decreases
- QueryInterface also increments the reference count
- C++ object + IUnkown = Com object
Identifiers
- Uses OSF DCE UUID (Universally Unique ID)
- Created using UuidCreate( ) = statistically unique 128 bit number
- IID = Interface ID
- CLSID = Class ID
- ProgID is a meaningful string which maps to the CLSID: in
Registry
in HKEY_CLASSES_ROOT
Using COM
- Initialize COM: CoInitialize
- Create COM Object (Class Factory Object):
CoCreateInstance
- InProc Servers: Server in DLL (in InprocServer32 in registry)
- Local Servers: Server in separate process (in LocalServer32 in
registry)
Uses Proxy DLL in client and Stub DLL in server to connect (usually RPC)
- Remote Servers: Use RPC
Some Definitions
- interface:
- a set of semantically related methods (function calls). Can be used to
provide access to the public member functions of an object. A COM interface is implemented
as a C++ V-table (in C++ programs) However the COM interface is language independent.
- virtual function:
- a function that can be redefined in a derived class and which can be
dynamically bound to any object in the inheritance hierarchy. Thus a pointer to the base
class could point to any object of a derived class and any function referenced by that
pointer is dynamically bound to the function of the correct derived class. This ability of
a function to be dynamically bound permits polymorphism.
- pure virtual function:
- A virtual function is undefined in the base class and must be defined in
any derived class. This allows a abstract base class to place requirements on any
inherited object class.
- polymorphism:
- The ability of a function in a program to work with any object in an
inheritance chain without recompilation. This implies that the run-time system must be
able to find the address of the function based on the type of the object at the time the
function is invoked (dynamic or late binding).
- v-table:
- a table containing the address of virtual functions. A v-table is
associated with each class.
- component:
- set of (possibly) related COM classes. Housed either in a DLL (Dynamically
Linked Library) or an executable file.
- idl (interface definition language):
- langauge independent/ platform independent means of specifiying a
function's prototype. Adapted from Open Software Foundation (OSF) RPC standard.
-
Let's develop a simple COM class, exploring the problems and solutions to them.
An Example: Chapter 2.
Project: write a simple COM object with one function which takes as input
two integers and returns their sum (this very simple object has no state).
We want this object to be language independent and location independent
(distributed).
PROBLEM: how to specify a language independent header file.
SOLUTION: Use IDL. The IDL file is compiled into language dependent code by MIDL
(Microsoft's IDL compiler)
// component.idl
import "unknwn.idl";
[ object, uuid(10000001-0000-0000-0000-000000000001) ]
interface ISum : IUnknown
{
HRESULT Sum([in] int x, [in] int y, [out, retval] int* retval);
};
- F1: Identifies this as a Com interface instead of a RPC specification.
- F2: Universally Unique identifier (128 bit (see page 35)), unique
across space and time.
- F3: Imported from "unknwn.idl" - All COM objects are derived
from this base class
the UUID of IUnknown is always 00000000-0000-0000-C000-0000000000046) - so it can be found
on every computer.
- F4: Information on movement of parameters
- in: parameter is input only (like call by value)
- out: parameter is output only (don't need to pass initial value to object) like
call by reference
- in, out: parameter is copied in and copied out.
- retval: this is the return value of the function for expression languages to
use as the "real" return value.
HRESULT is used by the COM run time system to check for COM errors.
Compiling the IDL will the language dependent files:
- component_i.c: defines UUID structure
- component.h: defines C++ code to access COM object from client program
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 3.01.75 */
/* at Sun Jan 17 11:56:28 1999
*/
/* Compiler settings for ..\component.idl:
Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
error checks: none
*/
//@@MIDL_FILE_HEADING( )
#include "rpc.h"
#include "rpcndr.h"
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __component_h__
#define __component_h__
#ifdef __cplusplus
extern "C"{
#endif
/* Forward Declarations */
#ifndef __ISum_FWD_DEFINED__
#define __ISum_FWD_DEFINED__
typedef interface ISum ISum;
#endif /* __ISum_FWD_DEFINED__ */
/* header files for imported files */
#include "unknwn.h"
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void __RPC_FAR * );
#ifndef __ISum_INTERFACE_DEFINED__
#define __ISum_INTERFACE_DEFINED__
/****************************************
* Generated header for interface: ISum
* at Sun Jan 17 11:56:28 1999
* using MIDL 3.01.75
****************************************/
/* [uuid][object] */
EXTERN_C const IID IID_ISum;
#if defined(__cplusplus) && !defined(CINTERFACE)
interface DECLSPEC_UUID("10000001-0000-0000-0000-000000000001")
ISum : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Sum(
/* [in] */ int x,
/* [in] */ int y,
/* [retval][out] */ int __RPC_FAR *retval) = 0;
};
#else /* C style interface */
typedef struct ISumVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
ISum __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
ISum __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
ISum __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Sum )(
ISum __RPC_FAR * This,
/* [in] */ int x,
/* [in] */ int y,
/* [retval][out] */ int __RPC_FAR *retval);
END_INTERFACE
} ISumVtbl;
interface ISum
{
CONST_VTBL struct ISumVtbl __RPC_FAR *lpVtbl;
};
#ifdef COBJMACROS
#define ISum_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define ISum_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define ISum_Release(This) \
(This)->lpVtbl -> Release(This)
#define ISum_Sum(This,x,y,retval) \
(This)->lpVtbl -> Sum(This,x,y,retval)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE ISum_Sum_Proxy(
ISum __RPC_FAR * This,
/* [in] */ int x,
/* [in] */ int y,
/* [retval][out] */ int __RPC_FAR *retval);
void __RPC_STUB ISum_Sum_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __ISum_INTERFACE_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif
- F5: generated from "import "unknwn.idl" in IDL file
- F6: allocation /deallocation function calls
- F7: defined in component_i.c
- F8: forces use of v-table
- F9: if this is C - build a virtual table by hand
- F10: In c++ this is derived from IUnknown
- F11: Simulates object's This pointer in C programs
- F12: Hide v-table and function pointers
- F13: for RPC access
Now let's see how a client can access this COM object:
PROBLEM: Creating an object in a language independent manner
SOLUTION: CoCreateInstance
PROBLEM: Returning an interface to the COM Object (like attaching a
v-table)
SOLUTION: QueryInterface Method
PROBLEM: managing a shared interface's lifetime
SOLUTION: AddRef and Release Methods
// client.cpp
#include <iostream.h>
#include "Component with Registration\component.h" // Generated by MIDL
// {10000002-0000-0000-0000-000000000001}
const CLSID CLSID_InsideDCOM = {0x10000002,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};
void main()
{
cout << "Client: Calling CoInitialize()" << endl;
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
cout << "CoInitialize failed" << endl;
IUnknown* pUnknown;
ISum* pSum;
cout << "Client: Calling CoCreateInstance()" << endl;
hr = CoCreateInstance(CLSID_InsideDCOM, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
if(FAILED(hr))
cout << "CoCreateInstance failed" << endl;
cout << "Client: Calling QueryInterface() for ISum on " << pUnknown << endl;
hr = pUnknown->QueryInterface(IID_ISum, (void**)&pSum);
// missing reference operator could crash the appliation
if(FAILED(hr))
cout << "IID_ISum not supported" << endl;
hr = pUnknown->Release();
cout << "Client: Calling pUnknown->Release() reference count = " << hr << endl;
int sum;
hr = pSum->Sum(2, 3, &sum);
if(SUCCEEDED(hr))
cout << "Client: Calling Sum(2, 3) = " << sum << endl;
hr = pSum->Release();
cout << "Client: Calling pSum->Release() reference count = " << hr << endl;
cout << "Client: Calling CoUninitialize()" << endl;
CoUninitialize();
}
- F14: Initializes the COM library, argument must be NULL
- F15: defined in unknwn.h - need pointer - because CoCreateInstance
will actually create the object
- F16: "Co" prefix is for "component Object Model"
- First parameter is UUID of COM class (Class ID: CLSID)
- second is Aggregation object
- third is context (inprocess as DLL, local or remote server
- fourth is interface ID in the class
- fifth is return value containing pointer to table of function calls
- F17: No can ask the COM object if it supports the ISum interface
- F18: No longer need the IUnknown interface
- F19: Call the object's only method
- F20: Closes COM library, braks RPC connections if any
Copyright chris wild 1999/2000.
For problems or questions regarding this web contact [Dr.
Wild].
Last updated: March 14, 2000.