forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			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__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |