30
COM and DCOM CS 562 February 27, 2001

COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Embed Size (px)

Citation preview

Page 1: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

COM and DCOM

CS 562

February 27, 2001

Page 2: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Motivation

Data Analyzer

Resource Monitor

int compute (…) {}

int compute (…) {}

Data Analyzer

int compute (…) {}

Resource Monitor

int compute (…) {}

Dynamically Linked Library

int compute (…) {}

Page 3: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Distributed Objects

• Object locator [registry]

• Communication– Data typing [interface]– Data representation [marshaling]– Synchronous/Asynchronous

• State persistence• System properties: Security, reliability, availability

Page 4: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

ArchitectureClient Server

Client Application Object Implementation

Proxy Stub

Channel

Client Application contains code to access functionality from an object

Server may run on same “local” machine, or “remote” machine

Registry Registry

Page 5: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

COM Basics

• Component Object Model (COM)

• COM is a specification that describes:

– What an object is

– How an object can manage itself over its lifetime

– How it tells the outside world what it can do

• COM is a binary specification, not a language

– Java, C++, VB, C

Page 6: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

COM object

• A COM class defines the implementation of one or more interfaces

• A COM object is instantiated from a COM class

• A Client application accesses a COM object through interface pointers

Client Application COM object

interface pointer

Page 7: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Interfaces

• List of functions

– name

– parameters

– return type

• A COM object can implement multiple interfaces

• Once a COM interface is published it can never change

Page 8: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

IUnknown

interface IUnknown { HRESULT QueryInterface (REFIID iid, void **ppvObject); ULONG AddRef (); ULONG Release ();}

• The ancestor of all Interfaces

• All COM objects must support this interface

– Provides reference counting for each interface

– Allows clients to locate appropriate interface

Page 9: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Registration of COM objects

• Interface ID (IID)– 128 bits. Statistically “Unique”

• Excel Worksheet– 00030000-0000-0000-C000-000000000046

• System Registry maintains all information– regsvr32.exe

Page 10: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

regedit utility

Page 11: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

COM IUnknown

interface IUnknown { HRESULT QueryInterface ([in] REFIID iid, [out] void **ppvObject); ULONG AddRef (); ULONG Release ();}

pInterface pQueryInterface

pAddRef

pRelease

Interface

QueryInterface (…)

AddRef ()

Release ()

Object

IUnknownCOM

Component

VTable

IUnknown

IAnother

IOneMore

Page 12: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

ISum example

pQueryInterface

pAddRef

pRelease

VTable

QueryInterface (…)

AddRef ()

Release ()

Object

IUnknown

ISum

IUnknownCOM

Component

ISum

pSum

Sum ()

pInterface

Page 13: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

ISum example

ULONG MiniCalc::AddRef() { return ++m_cRef; }

ULONG MiniCalc ::Release() { if (--m_cRef != 0) return m_cRef; delete this; return 0;}

HRESULT MiniCalc::QueryInterface (REFIID riid, void** ppv) { if (riid == IID_IUnknown) { *ppv = (IUnknown*) this; } else if (riid == IID_ISum) { *ppv = (ISum*)this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK;}

HRESULT MiniCalc ::Sum(int x, int y, int* retval) { *retval = x + y; return S_OK;}

class ISum : public IUnknown { public: virtual HRESULT Sum (int x, int y, int *retval) = 0;};

class MiniCalc : public ISum { public: // IUnknown ULONG AddRef(); ULONG Release(); HRESULT QueryInterface(REFIID iid, void** ppv);

// ISum HRESULT Sum(int x, int y, int* retval);

MiniCalc() : m_cRef(1) { } ~MiniCalc () {}

private: ULONG m_cRef;};

Page 14: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Implementing Interfaces in C++

• Multiple Inheritance

• Containment

• Aggregation

IUnknownCOM

Component

IMultiplyISum

[ object, uuid(10000001-0000-0000-0000-000000000001) ]interface ISum : IUnknown{

HRESULT Sum(int x, int y, [out, retval] int* retval);}

[ object, uuid(10000011-0000-0000-0000-000000000001) ]interface IMultiply : IUnknown{

HRESULT Multiply(int x, int y, [out, retval] int* retval);}

Page 15: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Multiple Inheritanceclass ISum : public IUnknown { public: virtual HRESULT Sum (int x, int y, int *retval) = 0;};

class IMultiply : public IUnknown { public: virtual HRESULT Multiply (int x, int y, int *retval) = 0;};

class MandS : public ISum, IMultiply { public: // IUnknown HRESULT QueryInterface(REFIID tiid, void **ppvObject); ULONG AddRef(); ULONG Release();

// Isum HRESULT Sum (int x, int y, int *retval);

// IMultiply HRESULT Multiply (int x, int y, int *retval); private: ULONG m_cRefs;}

MandS() : m_cRef(1) {}~MandS() {}

ULONG MandS ::AddRef() { return ++m_cRef; }

ULONG MandS ::Release() { if(--m_cRef != 0) return m_cRef; delete this; return 0;}

HRESULT MandS::QueryInterface(REFIID riid, void** ppv){ if (riid == IID_IUnknown) { *ppv = (IUnknown *) this; } else if (riid == IID_ISum) { *ppv = (Isum *) this; } else if (riid == IID_IMultiply) { *ppv = (Imultiply *) this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK;}

Reference Counting on Object Level!

Not on interface Level

Page 16: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

const CLSID CLSID_Container = {0x10000012,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

class Container : public IMultiply, ISum { public: // IUnknown HRESULT QueryInterface(REFIID tiid, void **ppvObject); ULONG AddRef(); ULONG Release();

// IMultiply HRESULT Multiply (int x, int y, int *retval);

// ISum HRESULT Sum (int x, int y, int *retval);

HResult Init(); private: ULONG m_cRef; ISum *m_pSum;}

Container::Container() : m_cRef(1), m_pSum(NULL) {}Container::~Container() { m_pSum->Release(); }

HRESULT Container::Init() { return CoCreateInstance(CLSID_Container, NULL, CLSCTX_INPROC_SERVER, IID_ISum, (void**)&m_pSum);}

HRESULT Container::Sum(int x, int y, int* retval) { return m_pSum->Sum(x, y, retval);}

HRESULT Container::Multiply(int x, int y, int* retval) { *retval = x * y; return S_OK;}

ULONG Container::AddRef() { return ++m_cRef; }ULONG Container::Release() { if (--m_cRef != 0) return m_cRef; delete this; return 0;}

Containment

IUnknown

ISum IMultiply

ISum

Page 17: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

const CLSID CLSID_ Aggregator = {0x10000022,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

class Aggregator : public IMultiply { public: // IUnknown HRESULT QueryInterface(REFIID tiid, void **ppvObject); ULONG AddRef(); ULONG Release();

// IMultiply HRESULT Multiply (int x, int y, int *retval);

Aggregator(); ~Aggregator(); HResult Init(); private: ULONG m_cRef; IUnknown* m_pUnknownInner;}

Aggregator::Aggregator() : m_cRef(1) {}Aggregator::~Aggregator() { m_pUnknownInner->Release(); }

HRESULT Aggregator::Init() { return CoCreateInstance(CLSID_Aggregator, (IUnknown*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_pUnknownInner);}

HRESULT Aggregator ::Sum(int x, int y, int* retval) { return m_pSum->Sum(x, y, retval);}

HRESULT Aggregator ::Multiply(int x, int y, int* retval) { *retval = x * y; return S_OK;}

AggregationHRESULT CAggregator::QueryInterface(REFIID riid, void** ppv) { if (riid == IID_IUnknown) { *ppv = (IUnknown*)this; } else if (riid == IID_ISum) { return m_pUnknownInner->QueryInterface(riid, ppv); } else if(riid == IID_IMultiply) { *ppv = (IMultiply*)this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK;} IUnknown

IMultiplyISum

IUnknown

Knows ISum and IMultiply

Page 18: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Reference counts

• A COM object must remember which of its interfaces are being used

– once refcount = 0, interface is no longer being used

– once all refcounts = 0 for all interfaces supported by an object, it can be shutdown

• Client code must be disciplined– when making a copy of an interface pointer, must manually increment refcount

– when finished with an interface, must manually decrement refcount

Page 19: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Accessing COM objects

const CLSID CLSID_Container = {0x10000012,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

main () { IMultiply* pMultiply; CoInitialize(NULL); // Get COM started

CoCreateInstance(CLSID_Container, // [in] RCLSID NULL, // [in] Outer Object (if any) CLSCTX_INPROC_SERVER, // [in] Access Context IID_IMultiply, // [in] RIID (of desired interface) (void**) &pMultiply); // [out] Interface Pointer

int multiply; hr = pMultiply->Multiply(4, 3, &multiply); if(SUCCEEDED(hr)) { // process }}

Page 20: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Accessing interfaces using interface pointer

// use existing interface pointer to locate other interface pointer

ISum* pSum;

pMultiply->QueryInterface(IID_ISum, (void**) &pSum);

int sum;

hr = pSum->Sum(4, 3, &sum);

if(SUCCEEDED(hr)) {

// process

}

hr = pMultiply->Release();

hr = pSum->Release();

CoUninitialize();

}

Responsibility of QueryInterface

Page 21: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Class Factoryconst CLSID CLSID_ Factory = {0x10000032,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

class CFactory : public IClassFactory { public: // IUnknown HRESULT QueryInterface(REFIID tiid, void **ppvObject); ULONG AddRef(); ULONG Release();

// IClassFactory HRESULT CreateInstance(IUnknown *pUnknownOuter, REFIID iid, void** ppv); HRESULT LockServer(BOOL bLock);

CFactory() : m_cRef(1) { } ~CFactory() { } private: ULONG m_cRef;};

ULONG CFactory::AddRef() { return ++m_cRef; }ULONG CFactory::Release() { if (--m_cRef != 0) return m_cRef; delete this; return 0;}

HRESULT CFactory::QueryInterface(REFIID iid, void** ppv) { if ((iid == IID_IUnknown) || (iid == IID_IClassFactory)) { *ppv = (IClassFactory *) this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK;}

HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID iid, void** ppv) { if (pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION; MiniCalc *pMiniCalc = new MiniCalc; if (pMiniCalc == NULL) return E_OUTOFMEMORY;

// QueryInterface probably for IID_IUNKNOWN HRESULT hr = pMiniCalc ->QueryInterface(iid, ppv); pMiniCalc ->Release(); return hr;}

Page 22: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Factory example// {10000002-0000-0000-0000-000000000001}const CLSID CLSID_Factory = {0x10000032,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};

void main(){ HRESULT hr = CoInitialize(NULL); IUnknown* pUnknown; ISum* pSum;

IClassFactory* pClassFactory; hr = CoGetClassObject(CLSID_Factory , CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void**)&pClassFactory);

pClassFactory->CreateInstance(NULL, IID_IUnknown, (void**)&pUnknown); pClassFactory->Release();

hr = pUnknown->QueryInterface(IID_ISum, (void**)&pSum); hr = pUnknown->Release();

int sum; hr = pSum->Sum(2, 3, &sum); if (SUCCEEDED(hr)) cout << "Client: Calling Sum(2, 3) = " << sum << endl;

hr = pSum->Release(); CoUninitialize();}

IClassFactory

ClassFactory

IUnknown

pCreateInstance

pLockServer

IUnknown

creates

Object

IUnknown

ISum

IUnknown

pAdd

Add

Page 23: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Object Countslong g_cComponents = 0;long g_cServerLocks = 0;

Container::Container() : m_cRef(1), m_pSum(NULL) { g_cComponents++; }Container::~Container() { g_cComponents--; }

HRESULT CFactory::LockServer(BOOL bLock) { if (bLock) g_cServerLocks++; else g_cServerLocks--; return S_OK;}

HRESULT DllCanUnloadNow() { if (g_cServerLocks == 0 && g_cComponents == 0) return S_OK; else return S_FALSE;}

HRESULT DllGetClassObject(REFCLSID clsid, REFIID iid, void** ppv) { if (clsid != CLSID_Aggregate) return CLASS_E_CLASSNOTAVAILABLE;

CFactory* pFactory = new CFactory; if (pFactory == NULL) return E_OUTOFMEMORY;

// QueryInterface probably for IClassFactory HRESULT hr = pFactory->QueryInterface(iid, ppv); pFactory->Release(); return hr;}

HRESULT DllRegisterServer() { return RegisterServer("aggregate.dll", CLSID_Container, "Aggregate", "Component.Aggregate", "Component.Aggregate.1", NULL);}

HRESULT DllUnregisterServer() { return UnregisterServer(CLSID_Aggregate, "Component.Aggregate", "Component.Aggregate.1");}

Page 24: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Context for COM object

• INPROC_SERVER

• INPROC_HANDLER

• LOCAL_SERVER

• REMOTE_SERVER

Page 25: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

INPROC_SERVER

• Dynamically Linked Library (DLL)

• COM object executes in same process space

IMultiply* pMultiply;

CoCreateInstance(CLSID_Container, [in] RCLSID NULL, [in] Outer Object CLSCTX_INPROC_SERVER, [in] ClsContext IID_IMultiply, [in] RIID (void**)&pMultiply); [out] Interface Pointer

Page 26: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

INPROC_HANDLER

• DLL with custom marshaling of data

Page 27: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

LOCAL_SERVER

• Executable (EXE)

• Dynamically Linked Library loaded into a surrogate process

Page 28: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

REMOTE_SERVER

• Executable (EXE) on a remote machine

• Dynamically Linked Library loaded into a surrogate process on a remote machine

Page 29: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

The Big Picture

ClientApplication

In-Process Server

In-ProcessObject

COM

Local ObjectProxy

Remote ObjectProxy

Client ProcessLocal Server Process

Remote Server Process

COM

Stub

COM

Stub

Local Server

Remote Server

LocalObject

RemoteObject

Remote Machine

Page 30: COM and DCOM CS 562 February 27, 2001. Motivation Data Analyzer Resource Monitor int compute (…) { } int compute (…) { } Data Analyzer int compute (…)

Under the Hood

Page 115 from DCOM