306 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // File: ComBase.h
 | |
| //
 | |
| // Desc: DirectShow base classes - defines a class hierarchy for creating
 | |
| //       COM objects.
 | |
| //
 | |
| // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| /*
 | |
| 
 | |
| a. Derive your COM object from CUnknown
 | |
| 
 | |
| b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
 | |
|    and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
 | |
|    to. The HRESULT * allows error codes to be passed around constructors and
 | |
|    the TCHAR * is a descriptive name that can be printed on the debugger.
 | |
| 
 | |
|    It is important that constructors only change the HRESULT * if they have
 | |
|    to set an ERROR code, if it was successful then leave it alone or you may
 | |
|    overwrite an error code from an object previously created.
 | |
| 
 | |
|    When you call a constructor the descriptive name should be in static store
 | |
|    as we do not copy the string. To stop large amounts of memory being used
 | |
|    in retail builds by all these static strings use the NAME macro,
 | |
| 
 | |
|    CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
 | |
|    if (FAILED(hr)) {
 | |
|        return hr;
 | |
|    }
 | |
| 
 | |
|    In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
 | |
|    knows not to do anything with objects that don't have a name.
 | |
| 
 | |
| c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
 | |
|    TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
 | |
|    error, or just simply pass it through to the constructor.
 | |
| 
 | |
|    The object creation will fail in the class factory if the HRESULT indicates
 | |
|    an error (ie FAILED(HRESULT) == TRUE)
 | |
| 
 | |
| d. Create a FactoryTemplate with your object's class id and CreateInstance
 | |
|    function.
 | |
| 
 | |
| Then (for each interface) either
 | |
| 
 | |
| Multiple inheritance
 | |
| 
 | |
| 1. Also derive it from ISomeInterface
 | |
| 2. Include DECLARE_IUNKNOWN in your class definition to declare
 | |
|    implementations of QueryInterface, AddRef and Release that
 | |
|    call the outer unknown
 | |
| 3. Override NonDelegatingQueryInterface to expose ISomeInterface by
 | |
|    code something like
 | |
| 
 | |
|      if (riid == IID_ISomeInterface) {
 | |
|          return GetInterface((ISomeInterface *) this, ppv);
 | |
|      } else {
 | |
|          return CUnknown::NonDelegatingQueryInterface(riid, ppv);
 | |
|      }
 | |
| 
 | |
| 4. Declare and implement the member functions of ISomeInterface.
 | |
| 
 | |
| or: Nested interfaces
 | |
| 
 | |
| 1. Declare a class derived from CUnknown
 | |
| 2. Include DECLARE_IUNKNOWN in your class definition
 | |
| 3. Override NonDelegatingQueryInterface to expose ISomeInterface by
 | |
|    code something like
 | |
| 
 | |
|      if (riid == IID_ISomeInterface) {
 | |
|          return GetInterface((ISomeInterface *) this, ppv);
 | |
|      } else {
 | |
|          return CUnknown::NonDelegatingQueryInterface(riid, ppv);
 | |
|      }
 | |
| 
 | |
| 4. Implement the member functions of ISomeInterface. Use GetOwner() to
 | |
|    access the COM object class.
 | |
| 
 | |
| And in your COM object class:
 | |
| 
 | |
| 5. Make the nested class a friend of the COM object class, and declare
 | |
|    an instance of the nested class as a member of the COM object class.
 | |
| 
 | |
|    NOTE that because you must always pass the outer unknown and an hResult
 | |
|    to the CUnknown constructor you cannot use a default constructor, in
 | |
|    other words you will have to make the member variable a pointer to the
 | |
|    class and make a NEW call in your constructor to actually create it.
 | |
| 
 | |
| 6. override the NonDelegatingQueryInterface with code like this:
 | |
| 
 | |
|      if (riid == IID_ISomeInterface) {
 | |
|          return m_pImplFilter->
 | |
|             NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
 | |
|      } else {
 | |
|          return CUnknown::NonDelegatingQueryInterface(riid, ppv);
 | |
|      }
 | |
| 
 | |
| You can have mixed classes which support some interfaces via multiple
 | |
| inheritance and some via nested classes
 | |
| 
 | |
| */
 | |
| 
 | |
| #ifndef __COMBASE__
 | |
| #define __COMBASE__
 | |
| 
 | |
| // Filter Setup data structures no defined in axextend.idl
 | |
| 
 | |
| typedef REGPINTYPES
 | |
| AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * FAR LPAMOVIESETUP_MEDIATYPE;
 | |
| 
 | |
| typedef REGFILTERPINS
 | |
| AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * FAR LPAMOVIESETUP_PIN;
 | |
| 
 | |
| typedef struct _AMOVIESETUP_FILTER
 | |
| {
 | |
|   const CLSID * clsID;
 | |
|   const WCHAR * strName;
 | |
|   DWORD      dwMerit;
 | |
|   UINT       nPins;
 | |
|   const AMOVIESETUP_PIN * lpPin;
 | |
| }
 | |
| AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
 | |
| 
 | |
| /* The DLLENTRY module initialises the module handle on loading */
 | |
| 
 | |
| extern HINSTANCE g_hInst;
 | |
| 
 | |
| /* On DLL load remember which platform we are running on */
 | |
| 
 | |
| extern DWORD g_amPlatform;
 | |
| extern OSVERSIONINFO g_osInfo;     // Filled in by GetVersionEx
 | |
| 
 | |
| /* Version of IUnknown that is renamed to allow a class to support both
 | |
|    non delegating and delegating IUnknowns in the same COM object */
 | |
| 
 | |
| #ifndef INONDELEGATINGUNKNOWN_DEFINED
 | |
| DECLARE_INTERFACE(INonDelegatingUnknown)
 | |
| {
 | |
|     STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
 | |
|     STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
 | |
|     STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
 | |
| };
 | |
| #define INONDELEGATINGUNKNOWN_DEFINED
 | |
| #endif
 | |
| 
 | |
| typedef INonDelegatingUnknown *PNDUNKNOWN;
 | |
| 
 | |
| 
 | |
| /* This is the base object class that supports active object counting. As
 | |
|    part of the debug facilities we trace every time a C++ object is created
 | |
|    or destroyed. The name of the object has to be passed up through the class
 | |
|    derivation list during construction as you cannot call virtual functions
 | |
|    in the constructor. The downside of all this is that every single object
 | |
|    constructor has to take an object name parameter that describes it */
 | |
| 
 | |
| class CBaseObject
 | |
| {
 | |
| 
 | |
| private:
 | |
| 
 | |
|     // Disable the copy constructor and assignment by default so you will get
 | |
|     //   compiler errors instead of unexpected behaviour if you pass objects
 | |
|     //   by value or assign objects.
 | |
|     CBaseObject(const CBaseObject& objectSrc);          // no implementation
 | |
|     void operator=(const CBaseObject& objectSrc);       // no implementation
 | |
| 
 | |
| private:
 | |
|     static LONG m_cObjects;     /* Total number of objects active */
 | |
| 
 | |
| protected:
 | |
| #ifdef DEBUG
 | |
|     DWORD m_dwCookie;           /* Cookie identifying this object */
 | |
| #endif
 | |
| 
 | |
| 
 | |
| public:
 | |
| 
 | |
|     /* These increment and decrement the number of active objects */
 | |
| 
 | |
|     CBaseObject(__in_opt LPCTSTR pName);
 | |
| #ifdef UNICODE
 | |
|     CBaseObject(__in_opt LPCSTR pName);
 | |
| #endif
 | |
|     ~CBaseObject();
 | |
| 
 | |
|     /* Call this to find if there are any CUnknown derived objects active */
 | |
| 
 | |
|     static LONG ObjectsActive() {
 | |
|         return m_cObjects;
 | |
|     };
 | |
| };
 | |
| 
 | |
| 
 | |
| /* An object that supports one or more COM interfaces will be based on
 | |
|    this class. It supports counting of total objects for DLLCanUnloadNow
 | |
|    support, and an implementation of the core non delegating IUnknown */
 | |
| 
 | |
| class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
 | |
|                  public CBaseObject
 | |
| {
 | |
| private:
 | |
|     const LPUNKNOWN m_pUnknown; /* Owner of this object */
 | |
| 
 | |
| protected:                      /* So we can override NonDelegatingRelease() */
 | |
|     volatile LONG m_cRef;       /* Number of reference counts */
 | |
| 
 | |
| public:
 | |
| 
 | |
|     CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk);
 | |
|     virtual ~CUnknown() {};
 | |
| 
 | |
|     // This is redundant, just use the other constructor
 | |
|     //   as we never touch the HRESULT in this anyway
 | |
|     CUnknown(__in_opt LPCTSTR Name, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr);
 | |
| #ifdef UNICODE
 | |
|     CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk);
 | |
|     CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk,__inout_opt HRESULT *phr);
 | |
| #endif
 | |
| 
 | |
|     /* Return the owner of this object */
 | |
| 
 | |
|     LPUNKNOWN GetOwner() const {
 | |
|         return m_pUnknown;
 | |
|     };
 | |
| 
 | |
|     /* Called from the class factory to create a new instance, it is
 | |
|        pure virtual so it must be overriden in your derived class */
 | |
| 
 | |
|     /* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
 | |
| 
 | |
|     /* Non delegating unknown implementation */
 | |
| 
 | |
|     STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
 | |
|     STDMETHODIMP_(ULONG) NonDelegatingAddRef();
 | |
|     STDMETHODIMP_(ULONG) NonDelegatingRelease();
 | |
| };
 | |
| 
 | |
| /* Return an interface pointer to a requesting client
 | |
|    performing a thread safe AddRef as necessary */
 | |
| 
 | |
| STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv);
 | |
| 
 | |
| /* A function that can create a new COM object */
 | |
| 
 | |
| typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(__in_opt LPUNKNOWN pUnkOuter, __inout_opt HRESULT *phr);
 | |
| 
 | |
| /*  A function (can be NULL) which is called from the DLL entrypoint
 | |
|     routine for each factory template:
 | |
| 
 | |
|     bLoading - TRUE on DLL load, FALSE on DLL unload
 | |
|     rclsid   - the m_ClsID of the entry
 | |
| */
 | |
| typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
 | |
| 
 | |
| /* Create one of these per object class in an array so that
 | |
|    the default class factory code can create new instances */
 | |
| 
 | |
| class CFactoryTemplate {
 | |
| 
 | |
| public:
 | |
| 
 | |
|     const WCHAR *              m_Name;
 | |
|     const CLSID *              m_ClsID;
 | |
|     LPFNNewCOMObject           m_lpfnNew;
 | |
|     LPFNInitRoutine            m_lpfnInit;
 | |
|     const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter;
 | |
| 
 | |
|     BOOL IsClassID(REFCLSID rclsid) const {
 | |
|         return (IsEqualCLSID(*m_ClsID,rclsid));
 | |
|     };
 | |
| 
 | |
|     CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) const {
 | |
|         CheckPointer(phr,NULL);
 | |
|         return m_lpfnNew(pUnk, phr);
 | |
|     };
 | |
| };
 | |
| 
 | |
| 
 | |
| /* You must override the (pure virtual) NonDelegatingQueryInterface to return
 | |
|    interface pointers (using GetInterface) to the interfaces your derived
 | |
|    class supports (the default implementation only supports IUnknown) */
 | |
| 
 | |
| #define DECLARE_IUNKNOWN                                        \
 | |
|     STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv) {      \
 | |
|         return GetOwner()->QueryInterface(riid,ppv);            \
 | |
|     };                                                          \
 | |
|     STDMETHODIMP_(ULONG) AddRef() {                             \
 | |
|         return GetOwner()->AddRef();                            \
 | |
|     };                                                          \
 | |
|     STDMETHODIMP_(ULONG) Release() {                            \
 | |
|         return GetOwner()->Release();                           \
 | |
|     };
 | |
| 
 | |
| 
 | |
| 
 | |
| HINSTANCE	LoadOLEAut32();
 | |
| 
 | |
| 
 | |
| #endif /* __COMBASE__ */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |