630 likes | 782 Views
Implementing COM Objects. 主講人:虞台文. Content. Types of COM Servers Objects with Single interface Example Enumerators Objects with Multiple interfaces Example Personal Account Server Modules of COM Class Factory & IClassFactory Example Simple Object Self-Registration
E N D
Implementing COM Objects 主講人:虞台文
Content • Types of COM Servers • Objects with Single interface • Example Enumerators • Objects with Multiple interfaces • Example Personal Account • Server Modules of COM • Class Factory & IClassFactory • Example Simple Object • Self-Registration • InProcess Severs by MFC
OLEObject Linking & Embedding Types of COM Servers
Call interface members Server Object Get object interface pointer, and return to Client Create object of a CLSID Locate implementation, and load or launch server CoCreateInstance() Using COM Object Client COM Library
Call interface members Server Object Get object interface pointer, and return to Client Create object of a CLSID Locate implementation, and load or launch server CoCreateInstance() Where is the server located? Client COM Library
Local server process Client Process In-process server In-process object COM Local server Stub Local object RPC COM Remote Machine Local object proxy Remote server process COM Remote server Stub Remote object Remote object proxy RPC Server Types Client
OLEObject Linking & Embedding Objects with Single Interface
Template of Enumerators template <class ELT_T> interface IEnum : IUnknown{virtual HRESULT Next(ULONG celt, ELT_T *rgelt, ULONG *pceltFetched)=0;virtual HRESULT Skip(ULONG celt)=0;virtual HRESULT Reset(void)=0;virtual HRESULT Clone(IEnum<ELT_T> ** ppEnum)=0;};
IEnumRECT // IEmnuRect.h #if !defined(IEnumRECT_HEARDER) #define IEnumRECT_HEARDER #include <objbase.h> #undef INTERFACE #define INTERFACE IEnumRECT DECLARE_INTERFACE_(IEnumRECT, IUnknown) { // IUnknown methods STDMETHOD(QueryInterface)(THIS_ REFIID, void **) PURE; STDMETHOD_(ULONG, AddRef)(THIS) PURE; STDMETHOD_(ULONG, Release)(THIS) PURE; // IEnumRECT methods STDMETHOD(Next)(THIS_ DWORD, LPRECT, LPDWORD) PURE; STDMETHOD(Skip)(THIS_ DWORD) PURE; STDMETHOD(Reset)(THIS) PURE; STDMETHOD(Clone)(THIS_ IEnumRECT **) PURE; }; // {6E699FBF-5ED3-44f2-A547-1481C54E130A} DEFINE_GUID(IID_IEnumRECT, 0x6e699fbf, 0x5ed3, 0x44f2, 0xa5, 0x47, 0x14, 0x81, 0xc5, 0x4e, 0x13, 0xa); typedef IEnumRECT * LPENUMRECT; #endif// !defined(IEnumRECT_HEARDER)
CEnumRect // EnumRect.cpp //..................................... #include <afxtempl.h> #include "IEnumRect.h" class CEnumRect : public IEnumRECT { private: DWORD m_cRef; //Reference count DWORD m_iCur; //Current enum position CArray<RECT, RECT> m_rects; //RECTS we enumerate public: CEnumRect(CArray<RECT, RECT>& rects); virtual ~CEnumRect(); //IUnknown members STDMETHODIMP QueryInterface(REFIID, void **); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); //IEnumRECT members STDMETHODIMP Next(ULONG, LPRECT, ULONG *); STDMETHODIMP Skip(ULONG); STDMETHODIMP Reset(void); STDMETHODIMP Clone(LPENUMRECT *); }; //.....................................
Constructor/Destructor CEnumRect::CEnumRect(CArray<RECT, RECT>& rects) { m_rects.Copy(rects); //Ref counts always start at zero m_cRef=0; //Current pointer is the first element m_iCur=0; } CEnumRect::~CEnumRect(void) { }
CEnumRect::QueryInterface STDMETHODIMP CEnumRect::QueryInterface(REFIID riid, void** ppv) { //Always NULL the out-parameters *ppv=NULL; // No explicit typecast necessary since we singly derive // from IEnumRECT. if (IID_IUnknown==riid || IID_IEnumRECT==riid) *ppv= this; // == (LPUNKNOWN) this; if (NULL==*ppv) return ResultFromScode(E_NOINTERFACE); //AddRef any interface we'll return. ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; }
CEnumRect::AddRef, Release STDMETHODIMP CEnumRect::AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) CEnumRect::Release(void) { if (0 != --m_cRef) return m_cRef; delete this; return 0; }
Exercise • Implementing objects with interfaces IEnumSentence and and IEnumWord for enumerating the sentences and words from a text file.
OLEObject Linking & Embedding Objects with Multiple Interfaces
Three Methods • Interface Implementations • Contained Interface Classes • Multiple Inheritance
IUnknown Personal Account IBanking IPettyCash Example: Personal Account
IBanking and IPettyCash // Account.h #if !defined(IBanking_IPettyCash_HEARDER) #define IBanking_IPettyCash_HEARDER #include <objbase.h> #undef INTERFACE #define INTERFACE IBanking DECLARE_INTERFACE_(IBanking, IUnknown) { // IUnknown methods STDMETHOD(QueryInterface)(THIS_ REFIID, void **) PURE; STDMETHOD_(ULONG, AddRef)(THIS) PURE; STDMETHOD_(ULONG, Release)(THIS) PURE; // IBanking methods STDMETHOD(Deposit)(THIS_ UINT) PURE; STDMETHOD(Withdraw)(THIS_ UINT) PURE; STDMETHOD(Balance)(THIS_ UINT *) PURE; }; // {8B5D2FC3-5633-423e-B846-4315F10F7C4A} DEFINE_GUID(IID_IBanking, 0x8b5d2fc3, 0x5633, 0x423e, 0xb8, 0x46, 0x43, 0x15, 0xf1, 0xf, 0x7c, 0x4a); typedef IBanking * LPBANKING;
IBanking and IPettyCash // Account.h #if !defined(IBanking_IPettyCash_HEARDER) #define IBanking_IPettyCash_HEARDER #include <objbase.h> #undef INTERFACE #define INTERFACE IBanking DECLARE_INTERFACE_(IBanking, IUnknown) { // IUnknown methods STDMETHOD(QueryInterface)(THIS_ REFIID, void **) PURE; STDMETHOD_(ULONG, AddRef)(THIS) PURE; STDMETHOD_(ULONG, Release)(THIS) PURE; // IBanking methods STDMETHOD(Deposit)(THIS_ UINT) PURE; STDMETHOD(Withdraw)(THIS_ UINT) PURE; STDMETHOD(Balance)(THIS_ UINT *) PURE; }; // {8B5D2FC3-5633-423e-B846-4315F10F7C4A} DEFINE_GUID(IID_IBanking, 0x8b5d2fc3, 0x5633, 0x423e, 0xb8, 0x46, 0x43, 0x15, 0xf1, 0xf, 0x7c, 0x4a); typedef IBanking * LPBANKING; #undef INTERFACE #define INTERFACE IPettyCash DECLARE_INTERFACE_(IPettyCash, IUnknown) { // IUnknown methods STDMETHOD(QueryInterface)(THIS_ REFIID, void **) PURE; STDMETHOD_(ULONG, AddRef)(THIS) PURE; STDMETHOD_(ULONG, Release)(THIS) PURE; // IPettyCash methods STDMETHOD(Income)(THIS_ UINT) PURE; STDMETHOD(Pay)(THIS_ UINT) PURE; STDMETHOD(Cash)(THIS_ UINT *) PURE; }; // {7DCD4D1B-085E-40a7-93FE-4123E6F4C726} DEFINE_GUID(IID_IPettyCash, 0x7dcd4d1b, 0x85e, 0x40a7, 0x93, 0xfe, 0x41, 0x23, 0xe6, 0xf4, 0xc7, 0x26); typedef IPettyCash * LPPETTYCASH; #endif// !defined(IBanking_IPettyCash_HEARDER)
Three Methods • Interface Implementations • Contained Interface Classes • Multiple Inheritance
Exercise • Define interfaces for an object which manages personal data used in usual life, e.g., personal information and address book. You also need an interface (e.g., IPersistFile) to access the information from a file. • Implement the personal-data object including the interfaces you defined using the three methods described in this lecture. • Write an MFC application using the personal-data object.
OLEObject Linking & Embedding Server Modules of COM
Implementation can be independent of execution context. Object Class factory: Creates objects Implementation differs between DLL and EXE servers. The Generic Structure of a Server Module Object interfaces (as many as desired) IClassFactory(2) Registration Exposure for Class factory Unloading mechanism Sever module
Registry Entries In-process servers: InprocServer32=<path to DLL> Object handlers: InprocHandler32=<path to DLL> Local servers: LocalServer32=<path to EXE>
Self-Registration • DLL Servers • DllRegisterServer • DllUnregisterServer • EXE servers Command arguments • /RegServer • /UnregServer
Server Emulation \ CLSID {42754580-16b7-11ce-80eb-00aa003d7352} = Original ComponentTreatAs = {6fa820f0-2e48-11ce-80eb-00aa003d7352}AutoTreatAs = {6fa820f0-2e48-11ce-80eb-00aa003d7352}InprocServer32 = c:\older\original.dll {6fa820f0-2e48-11ce-80eb-00aa003d7352} = New Emulating ComponentInprocServer32 = c:\newer\emulator.dll
Some API’s • CoGetClassObject • CoCreateInstance(Ex) • CoGetTreatAsClass • CoTreatAsClass
Exercises • Read the APIs for server emulations. • Lookup system registry to find some entries with TreatAs and AutoTreatAs keys.
OLEObject Linking & Embedding Class Factory & IClassFactory
Server Class factory (an object) Client Object The Class-Factory Object IClassFactory- ::CreateInstance Factory manufactures object. Factory returns New interface Pointer to client
IClassFactory interface IClassFactory : IUnknown{ HRESULT CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv); HRESULT LockServer(BOOL fLock);};
Licensing with IClassFactory2 interface IClassFactory2 : IClassFactory{ HRESULT GetLicInfo(LPLICINFO pLicInfo); HRESULT RequestLicKey(DWORD dwResrved, BSTR FAR* pbstrKey); HRESULT CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID riid, BSTR bstrKey, void **ppvObject);};
Exposing the Class Factory In-Process Server • Implement DllGetClassObject • Implement DllCanUnloadNow STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv); STDAPI DllCanUnloadNow(void);
Exposing the Class Factory Local Server • CoRegisterClassObject • CoRevokeClassObject STDAPI CoRegisterClassObject( REFCLSID rclsid, IUnknown * pUnk, DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister ); HRESULT CoRevokeClassObject(DWORDdwRegister);
In-Process-Server Creation
Local-Server Creation
Create Multiple COM Objects Step1. Get IClassFactory by Step2. Call IClassFactory::CreateInstance(…)a number of time if multiple objects are needed Step3. Call IClassFactory::Release(). STDAPI CoGetClassObject( REFCLSID rclsid, //CLSID associated with the class object DWORD dwClsContext, //Context for running executable code COSERVERINFO * pServerInfo, //Pointer to machine on which the object is to // be instantiated REFIID riid, //Reference to the identifier of the interface LPVOID * ppv //Address of output variable that receives the // interface pointer requested in riid );
Create Single COM Objects STDAPI CoCreateInstance( REFCLSID rclsid, //Class identifier (CLSID) of the object LPUNKNOWN pUnkOuter, //Pointer to controlling IUnknown DWORD dwClsContext, //Context for running executable code REFIID riid, //Reference to the identifier of the interface LPVOID * ppv //Address of output variable that receives // the interface pointer requested in riid );
CoGetClassObject() vs. CoCreateInstance() STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwContext, REFIID iid, void **ppv){ HRESULT hr; IClassFactory *pCF; *ppv=NULL; hr=CoGetClassObject(rclsid, dwContext, NULL, IID_IClassFactory, (void **) &pCF);if (FAILED(hr)) return hr; hr=pCF->CreateInstance(pUnkOuter, iid, ppv); pCF->Release(); return hr;}
OLEObject Linking & Embedding Example Simple Object
Exercises • The above example create COM object using CoCreateInstance(). Modify it by using class factory. • Modify the server of the above example so that it can create multiple classes of COM object. • Code the problem in Exercise 3 as an in-process server, and write an MFC application to use the object.
OLEObject Linking & Embedding Self-Registration
Some Registry Functions • RegCreateKey(Ex) • RegSetValue(Ex) • RegCloseKey • RegOpenKey(Ex) • RegEnumKey(Ex) • RegEnumValue • RegQueryInfoKey • RegDeleteKey
DEF File ;DSimpleObject.def : 聲明動態庫DLL的模組參數. LIBRARY DSimpleObject DESCRIPTION '我的第一個純 C++ COM 對象' EXPORTS DllRegisterServer PRIVATE ; COM server registration DllUnregisterServer PRIVATE ; COM server deregistration DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE