ClassFactory.h
Upload User: geng8029
Upload Date: 2021-01-30
Package Size: 187k
Code Size: 6k
Category:

Audio program

Development Platform:

Visual C++

  1. #pragma once
  2. // Class Factory implementation
  3. /* 
  4. // Example of usage:
  5. // g_ClassFactories: Array of class factory data.
  6. // Defines a look-up table of CLSIDs and corresponding creation functions.
  7. ClassFactoryData g_ClassFactories[] =
  8. {
  9.     {   &CLSID_MyObject, MyObject::CreateInstance }
  10. };
  11. DWORD g_numClassFactories = ARRAY_SIZE(g_ClassFactories);
  12. // Defines the static ClassFactory::m_serverLocks member. 
  13. DEFINE_CLASSFACTORY_SERVER_LOCK;
  14. STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv)
  15. {
  16.     ClassFactory *pFactory = NULL;
  17.     HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; // Default to failure
  18.     // Find an entry in our look-up table for the specified CLSID.
  19.     for (DWORD index = 0; index < g_numClassFactories; index++)
  20.     {
  21.         if (*g_ClassFactories[index].pclsid == clsid)
  22.         {
  23.             // Found an entry. Create a new class factory object.
  24.             pFactory = new ClassFactory(g_ClassFactories[index].pfnCreate);
  25.             if (pFactory)
  26.             {
  27.                 hr = S_OK;
  28.             }
  29.             else
  30.             {
  31.                 hr = E_OUTOFMEMORY;
  32.             }
  33.             break;
  34.         }
  35.     }
  36.     if (SUCCEEDED(hr))
  37.     {
  38.         hr = pFactory->QueryInterface(riid, ppv);
  39.     }
  40.     SAFE_RELEASE(pFactory);
  41.     return hr;
  42. }
  43. STDAPI DllCanUnloadNow()
  44. {
  45.     if (!ClassFactory::IsLocked())
  46.     {
  47.         return S_OK;
  48.     }
  49.     else
  50.     {
  51.         return S_FALSE;
  52.     }
  53. }
  54. */
  55. namespace MediaFoundationSamples
  56. {
  57.     // Function pointer for creating COM objects. (Used by the class factory.)
  58.     typedef HRESULT (*CreateInstanceFn)(IUnknown *pUnkOuter, REFIID iid, void **ppv);
  59.     // Structure to associate CLSID with object creation function.
  60.     struct ClassFactoryData
  61.     {
  62.         const GUID          *pclsid;
  63.         CreateInstanceFn    pfnCreate;
  64.     };
  65.     // ClassFactory:
  66.     // Implements a class factory for COM objects.
  67.     class ClassFactory : public IClassFactory
  68.     {
  69.     private:
  70.         volatile long           m_refCount;     // Reference count.
  71.         static volatile long    m_serverLocks;  // Number of server locks
  72.         CreateInstanceFn        m_pfnCreation;  // Function to create an instance of the object.
  73.     public:
  74.         ClassFactory(CreateInstanceFn pfnCreation) : m_pfnCreation(pfnCreation), m_refCount(1)
  75.         {
  76.         }
  77.         static bool IsLocked()
  78.         {
  79.             return (m_serverLocks != 0);
  80.         }
  81.         STDMETHODIMP_(ULONG) AddRef()
  82.         {
  83.             return InterlockedIncrement(&m_refCount);
  84.         }
  85.         STDMETHODIMP_(ULONG) Release()
  86.         {
  87.             assert(m_refCount >= 0);
  88.             ULONG uCount = InterlockedDecrement(&m_refCount);
  89.             if (uCount == 0)
  90.             {
  91.                 delete this;
  92.             }
  93.             // Return the temporary variable, not the member
  94.             // variable, for thread safety.
  95.             return uCount;
  96.         }
  97.         // IUnknown methods
  98.         STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
  99.         {
  100.             if (NULL == ppv)
  101.             {
  102.                 return E_POINTER;
  103.             }
  104.             else if (riid == __uuidof(IUnknown))
  105.             {
  106.                 *ppv = static_cast<IUnknown*>(this);
  107.             }
  108.             else if (riid == __uuidof(IClassFactory))
  109.             {
  110.                 *ppv = static_cast<IClassFactory*>(this);
  111.             }
  112.             else 
  113.             {
  114.                 *ppv = NULL;
  115.                 return E_NOINTERFACE;
  116.             }
  117.             AddRef();
  118.             return S_OK;
  119.         }
  120.         STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)
  121.         {
  122.             // If the caller is aggregating the object, the caller may only request
  123.             // IUknown. (See MSDN documenation for IClassFactory::CreateInstance.)
  124.             if (pUnkOuter != NULL)
  125.             {
  126.                 if (riid != __uuidof(IUnknown))
  127.                 {
  128.                     return E_NOINTERFACE;
  129.                 }
  130.             }
  131.             return m_pfnCreation(pUnkOuter, riid, ppv);
  132.         }
  133.         STDMETHODIMP LockServer(BOOL lock)
  134.         {   
  135.             if (lock)
  136.             {
  137.                 LockServer();
  138.             }
  139.             else
  140.             {
  141.                 UnlockServer();
  142.             }
  143.             return S_OK;
  144.         }
  145.         // Static methods to lock and unlock the the server.
  146.         static void LockServer()
  147.         {
  148.             InterlockedIncrement(&m_serverLocks);
  149.         }
  150.         static void UnlockServer()
  151.         {
  152.             InterlockedDecrement(&m_serverLocks);
  153.         }
  154.     };
  155.     // BaseObjects
  156.     // All COM objects that are implemented in the server (DLL) must derive from BaseObject
  157.     // so that the server is not unlocked while objects are still active.
  158.     class BaseObject
  159.     {
  160.     public:
  161.         BaseObject() 
  162.         {
  163.             ClassFactory::LockServer();
  164.         }
  165.         virtual ~BaseObject()
  166.         {
  167.             ClassFactory::UnlockServer();
  168.         }
  169.     };
  170.     // RefCountedObject
  171.     // You can use this when implementing IUnknown or any object that uses reference counting.
  172.     class RefCountedObject
  173.     {
  174.     protected:
  175.         volatile long   m_refCount;
  176.     public:
  177.         RefCountedObject() : m_refCount(1) {}
  178.         virtual ~RefCountedObject()
  179.         {
  180.             assert(m_refCount == 0);
  181.         }
  182.         ULONG AddRef()
  183.         {
  184.             return InterlockedIncrement(&m_refCount);
  185.         }
  186.         ULONG Release()
  187.         {
  188.             assert(m_refCount > 0);
  189.             ULONG uCount = InterlockedDecrement(&m_refCount);
  190.             if (uCount == 0)
  191.             {
  192.                 delete this;
  193.             }
  194.             return uCount;
  195.         }
  196.     };
  197. #define DEFINE_CLASSFACTORY_SERVER_LOCK  volatile long ClassFactory::m_serverLocks = 0;
  198. }; // namespace MediaFoundationSamples