Saturday, July 12, 2014

Component Object Model (COM) using C++

Component Object Model


Syllabus

  • Component architecture
  • Component Object Model–COM
  • Interfaces
  • IUnknown 
  • Component life time
  • Components and servers
  • HRESULTS and GUIDS
  • COM registry entries 
  • COM library functions 
  • Class factories
  • Server activation and component creation 
  • COM servers in EXE 
  • Interface description language (IDL) 
  • MIDL 
  • Type libraries

Component Architecture

  • Monolithic Application
  • Component Application
  • Component Benefits
    • Application Evolve over time
    • Application Customization
    • Component Libraries
    • Distributed Components
  • Component Requirements
    • Dynamic Linking
    • Encapsulation
  • Encapsulation leads to following constraints
    • Components should have language independence
    • Components should be in binary form
    • Components must be up-gradable
    • Components must be transparently relocatable on the network

Component Object Model

  • Component Object Model (COM) is a specification for a way of creating components and building applications from these components
  • COM provides library of standard functions
  • COM components meets all the requirements of the component architecture
    • Language Independent
    • Binary Form
    • Upgradable
    • Relocatable

Interfaces

  • An interface provides connection between two different objects
  • Interface Features
    • Interfaces are immutable
    • Interfaces provide polymorphizm
  • Memory layout of an interface
    • vTable - Virtual Table
    • VTable pointer

IUnknown

  • Definition of IUnknown
    • QueryInterface
    • AddRef
    • Release
  • QueryInterface Rules
    • You always get the same IUnknown
    • You can always get an interface if you got it before
    • It is Symmetric
    • It is Transitive
    • It is Reflexive

Component Life Cycle

  • Component should take care of controlling its own lifetime
  • Reference Counting
  • Implementing AddRef and Release methods

Reference Counting Rules

  • Call AddRef before returning
  • Call Release when you are done
  • Call AddRef after assignment

Components and Servers

  • COM Component is a unit of functionality that implements one or more interfaces
  • COM Object server is either an executable or a DLL that hosts and create one or more COM components

COM Object Server in a DLL

  • COM DLL Server exports following five functions
    • DllMain
    • DllCanUnloadNow
    • DllGetClassObject
    • DllRegisterServer
    • DllUnregisterServer

HRESULTS and GUIDS

  • HRESULT
    • Facility(31-16) + Return Code(15 - 0)
  • GUID
    • UUID
    • IID
    • CLSID
    • GUID

COM Registry Entries

  • COM Components use registry to convey information about the location of their servers
  • A COM Dll Server is required to make these entries when the exported function DllRegisterServer is called
  • The COM library function CoGetClassObject takes the class id of the component and then looks into the registry to find the file name of the server in which component is hosted
  • Other COM Registry entires
    • PROGID or programmatic ID
    • AppID
    • Component Categories
    • Interface
    • TypeLib

COM Library Functions

  • The COM library is implemented in Ole32.dll
  • Some important COM library functions
    • CoInitialize/CoInitializeEx
    • CoUninitialize
    • CoGetClassObject
    • CoCreateInstance

Class Factories

  • A class factory is a COM component that creates other components that correspond only to a single, specific CLSID
  • The standard interface for creating components is IClassFactory or IClassFactory2

Server Activation and Component Creation

  • Client creating a component

COM Servers in EXE

  • Local Procedure call, Marshalling, and Proxy/Stub Dlls
  • Function call for out-of-proc components

Interface Description Language

  • Interface Description Language (IDL) is used to describe COM interfaces in a standard way
  • IDL is used to create proxy/stub Dlls and type libraries (TLB's)

MIDL

  • Microsoft IDL (MIDL) compiler is used to generate proxy and stub Dll's from IDL
  • MIDL also generates other helper files
  • Command Line: MIDL IX.idl
  • Files generated by MIDL compiler
    • IX.h
    • IX_P.c
    • IX_I.c
    • DLLDATA.c
    • makefile
    • IX.DEF

Type Libraries

  • Type libraries provides type information of components, interfaces, methods, properties, arguments and structures
  • Distributing Type Libraries
  • Using Type Libraries
    • LoadRegTypeLib
    • LoadTypeLib
    • RegisterTypeLib
    • UnRegisterTypeLib
  • Importing Type Library definitions in C++
    • #import "filename" [attributes]

Sample Code Snippets


Follow the steps mentioned in this walkthrough to create ATL based COM server and client in C++ using Visual Studio integrated development environment (IDE) and its wizards.

Server.idl

// Server.idl : IDL source for Server
//

// This file will be processed by the MIDL tool to
// produce the type library (Server.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(ABF4D15B-E5E5-42DF-9D6B-18E8DA308524),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IComServer : IDispatch {
    [id(1), helpstring("HelloWorld")] HRESULT HelloWorld([in] BSTR bstrString);
};
[
    uuid(AC45CE17-5C08-480C-A074-E02DB37DBE3F),
    version(1.0),
]
library ServerLib
{
    importlib("stdole2.tlb");
    [
        uuid(8C97F393-3695-4CD2-9DE0-6B42DF4F2071)
    ]
    coclass ComServer
    {
        [default] interface IComServer;
    };
};
      
 

ComServer.hpp

// ComServer.hpp : Declaration of the CComServer

#pragma once
#include "resource.h"       // main symbols

#include "Server_i.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;

// CComServer

class ATL_NO_VTABLE CComServer :
    public CComObjectRootEx,
    public CComCoClass,
    public IDispatchImpl
{
public:
    CComServer()
    {
    }

    DECLARE_REGISTRY_RESOURCEID(IDR_COMSERVER)

    BEGIN_COM_MAP(CComServer)
        COM_INTERFACE_ENTRY(IComServer)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

public:

    STDMETHOD(HelloWorld)(BSTR bstrString);
};

OBJECT_ENTRY_AUTO(__uuidof(ComServer), CComServer)
       
 

ComServer.cpp

// ComServer.cpp : Implementation of CComServer

#include "stdafx.h"
#include "ComServer.h"

// CComServer

STDMETHODIMP CComServer::HelloWorld(BSTR bstrString)
{
    // TODO: Add your implementation code here
    printf("%S \n\n", bstrString);

    return S_OK;
}
       
 

Cllient.cpp

// Client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "atlbase.h"
#import "..\\Server\\\x64\\Release\\Server.tlb" no_namespace

int main()
{
    CoInitialize(nullptr);

    CComPtr pIComServer = nullptr;

    pIComServer.CoCreateInstance(__uuidof(ComServer));
    HRESULT hr = pIComServer->HelloWorld(L"Hello World! from client.");

    if (FAILED(hr))
    printf("Some error occured !\n");

    pIComServer.Release();
    pIComServer = nullptr;

    CoUninitialize();
    return 0;
}

Register/Un-register a Server Component

// Use below command to register the server
> regsvr32 Server.dll

// Use below command to un-register the server
> regsvr32 /u Server.dll

When you run the client program you should see the output printed by server component as below.


Recommended Book





 
biz.