Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

319 lines
11 KiB

//+-------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000 - 2000
//
// File: comobjects.h
//
// Contents: Base code for com objects exported by Object Model.
//
// Classes: CMMCStrongReferences, CMMCIDispatchImpl
//
// History: 16-May-2000 AudriusZ Created
//
//--------------------------------------------------------------------
#pragma once
#ifndef COMOBJECTS_H_INCLUDED
#define COMOBJECTS_H_INCLUDED
/*+-------------------------------------------------------------------------*
* class CComObjectObserver
*
* PURPOSE: The general interface for a class that observes com object events
*
* USAGE: Used by CMMCIDispatchImpl, so all ObjectModel objects inherit from it
*
*+-------------------------------------------------------------------------*/
class CComObjectObserver : public CObserverBase
{
public:
// request to break external references
virtual SC ScOnDisconnectObjects() {DEFAULT_OBSERVER_METHOD;}
};
/*+-------------------------------------------------------------------------*
* function GetComObjectEventSource
*
* PURPOSE: returns singleton for emmiting Com Object Events
* Since ObjectModel com objects are implemented in EXE and DLL's
* There is a need to have 'global' object per process to
* be able to bradcast events to every object.
*
* USAGE: Used by
* 1) CMMCIDispatchImpl to register objects
* 2) CAMCMultiDocTemplate to bradcast 'cut off extenal references'
*+-------------------------------------------------------------------------*/
MMCBASE_API CEventSource<CComObjectObserver>& GetComObjectEventSource();
/***************************************************************************\
*
* CLASS: CMMCStrongReferences
*
* PURPOSE: Implements static interface to count strong references put on MMC
* Also implements the method to detect when the last stron reference was
* released in order to start MMC exit procedure.
*
* Class is implemented as singleton object in mmcbase.dll
*
* USAGE: use CMMCStrongReferences::AddRef() and CMMCStrongReferences::Release()
* to put/remove strong references on MMC.EXE
* use CMMCStrongReferences::LastRefReleased() to inspect if the
* last ref was released
*
\***************************************************************************/
class MMCBASE_API CMMCStrongReferences
{
public:
// public (static) interface
static DWORD AddRef();
static DWORD Release();
static bool LastRefReleased();
private:
// implementation helpers
CMMCStrongReferences();
static CMMCStrongReferences& GetSingletonObject();
DWORD InternalAddRef();
DWORD InternalRelease();
bool InternalLastRefReleased();
// data members
DWORD m_dwStrongRefs; // strong reference count
bool m_bLastRefReleased; // have strong reference count ever go from one to zero
};
/***************************************************************************\
*
* CLASS: CMMCIDispatchImpl<typename _ComInterface, const GUID * _pguidClass = &GUID_NULL, const GUID* _pLibID = &LIBID_MMC20>
* _ComInterface - Object Model interface implemented by the class
* _pguidClass [optional] - pointer to CLSID for cocreatable objects
* _pLibID [optional] - pointer to LIBID with _ComInterface's type info
*
* PURPOSE: Base for every com object defined by the MMC Object Model
* implements common functionality, like:
* - IDispatch
* - ISupportErrorInfo
* - IExternalConnection
*
* USAGE: Derive your object from CMMCIDispatchImpl<interface>
* Define: BEGIN_MMC_COM_MAP(_Class) ... END_MMC_COM_MAP() in the class
* Define COM_INTERFACE_ENTRY for each additional interface
* ( DO NOT need to add IDispatch, ISupportErrorInfo, IExternalConnection
* or implemented ObjecModel interface - these are added by the base class )
*
\***************************************************************************/
template<
typename _ComInterface,
const GUID * _pguidClass = &GUID_NULL,
const GUID * _pLibID = &LIBID_MMC20>
class CMMCIDispatchImpl :
public IDispatchImpl<_ComInterface, &__uuidof(_ComInterface), _pLibID>,
// we can use the IMMCSupportErrorInfoImpl object because exactly one dispinterface is exposed from this object.
public IMMCSupportErrorInfoImpl<&__uuidof(_ComInterface), _pguidClass>,
public IExternalConnection,
public CComObjectRoot,
public CComObjectObserver
{
public:
// typedef interface and this class [used by macros defined in the derived class]
typedef _ComInterface MMCInterface;
typedef CMMCIDispatchImpl<_ComInterface, _pguidClass, _pLibID> CMMCIDispatchImplClass;
// interfaces implemented by this base class
BEGIN_COM_MAP(CMMCIDispatchImplClass)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IExternalConnection)
END_COM_MAP()
CMMCIDispatchImpl()
{
// add itself as an observer for com object events
GetComObjectEventSource().AddObserver(*static_cast<CComObjectObserver*>(this));
#ifdef _MMC_NODE_MANAGER_ONLY_
// Every object implemented by node manager should also register for typeinfo clenup
static CMMCTypeInfoHolderWrapper wrapper(GetInfoHolder());
#endif // _MMC_NODE_MANAGER_ONLY_
}
#ifdef _MMC_NODE_MANAGER_ONLY_
// Every object implemented by node manager should also register for typeinfo clenup
// the porpose of this static function is to ensure _tih is a static variable,
// since static wrapper will hold on its address - it must be always valid
static CComTypeInfoHolder& GetInfoHolder() { return _tih; }
#endif // _MMC_NODE_MANAGER_ONLY_
// implementation for IExternalConnection methods
STDMETHOD_(DWORD, AddConnection)(DWORD extconn, DWORD dwreserved)
{
DWORD dwRefs = AddRef(); // addref itself
// put a strong reference on MMC - this will prevent mmc from exiting
if (extconn & EXTCONN_STRONG)
dwRefs = CMMCStrongReferences::AddRef();
return dwRefs;
}
STDMETHOD_(DWORD, ReleaseConnection)(DWORD extconn, DWORD dwreserved, BOOL fLastReleaseCloses)
{
DWORD dwStrongRefs = 0;
DWORD dwRefs = 0;
// release a strong reference on MMC
if (extconn & EXTCONN_STRONG)
{
dwStrongRefs = CMMCStrongReferences::Release();
}
//release a ref on itself
dwRefs = Release();
// return a proper ref count
return (extconn & EXTCONN_STRONG) ? dwStrongRefs : dwRefs;
}
/***************************************************************************\
*
* METHOD: ScOnDisconnectObjects
*
* PURPOSE: invoked when observed event (request to disconnect) occures
* Disconnects from external connections
*
* PARAMETERS:
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
virtual ::SC ScOnDisconnectObjects()
{
DECLARE_SC(sc, TEXT("CMMCIDispatchImpl<_ComInterface>::ScOnDisconnectObjects"));
// QI for IUnknown
IUnknownPtr spUnknown = this;
// sanity check
sc = ScCheckPointers( spUnknown, E_UNEXPECTED );
if (sc)
return sc;
// cutt own references
sc = CoDisconnectObject( spUnknown, 0/*dwReserved*/ );
if (sc)
return sc;
return sc;
}
#ifdef DBG
// this block is to catch mistakes when the Derived class does not use
// BEGIN_MMC_COM_MAP() or END_MMC_COM_MAP() in its body
virtual void _BEGIN_MMC_COM_MAP() = 0;
virtual void _END_MMC_COM_MAP() = 0;
#endif
};
/***************************************************************************\
*
* MACRO: BEGIN_MMC_COM_MAP
*
* PURPOSE: To be used in place of BEGIN_MMC_COM_MAP for com objects used in MMC Object Model
*
\***************************************************************************/
#ifndef DBG
// standard version
#define BEGIN_MMC_COM_MAP(_Class) \
BEGIN_COM_MAP(_Class) \
COM_INTERFACE_ENTRY(MMCInterface)
#else // DBG
// same as above, but shuts off the trap placed in CMMCIDispatchImpl in debug mode
#define BEGIN_MMC_COM_MAP(_Class) \
virtual void _BEGIN_MMC_COM_MAP() {} \
BEGIN_COM_MAP(_Class) \
COM_INTERFACE_ENTRY(MMCInterface)
#endif // DBG
/***************************************************************************\
*
* MACRO: END_MMC_COM_MAP
*
* PURPOSE: To be used in place of END_COM_MAP for com objects used in MMC Object Model
*
\***************************************************************************/
#ifndef DBG
// standard version
#define END_MMC_COM_MAP() \
COM_INTERFACE_ENTRY_CHAIN(CMMCIDispatchImplClass) \
END_COM_MAP()
#else // DBG
// same as above, but shuts off the trap placed in CMMCIDispatchImpl in debug mode
#define END_MMC_COM_MAP() \
COM_INTERFACE_ENTRY_CHAIN(CMMCIDispatchImplClass) \
END_COM_MAP() \
virtual void _END_MMC_COM_MAP() {}
#endif // DBG
/*+-------------------------------------------------------------------------*
* class CConsoleEventDispatcher
*
*
* PURPOSE: Interface for emitting com events from node manager side
* implemented by CMMCApplication
*
*+-------------------------------------------------------------------------*/
class CConsoleEventDispatcher
{
public:
virtual SC ScOnContextMenuExecuted( PMENUITEM pMenuItem ) = 0;
};
/***************************************************************************\
*
* METHOD: CConsoleEventDispatcherProvider
*
* PURPOSE: this class is to wrap and maintain a pointer to CConsoleEventDispatcher
* interface. Pointer is set by conui side and used from node manager side.
* Pointer is discarded when when cleanup event is observed.
*
\***************************************************************************/
class CConsoleEventDispatcherProvider
{
public:
// public class members (static) to get/set interface pointer
static SC MMCBASE_API ScSetConsoleEventDispatcher( CConsoleEventDispatcher *pDispatcher )
{
s_pDispatcher = pDispatcher;
return SC(S_OK);
}
static SC MMCBASE_API ScGetConsoleEventDispatcher( CConsoleEventDispatcher *&pDispatcher )
{
pDispatcher = s_pDispatcher;
return SC(S_OK);
}
private:
// pointer to interface
static MMCBASE_API CConsoleEventDispatcher *s_pDispatcher;
};
#endif // COMOBJECTS_H_INCLUDED