windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvoice/dxvclassfac.cpp
2020-09-26 16:20:57 +08:00

316 lines
7.2 KiB
C++

/*==========================================================================
*
* Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
*
* File: classfac.c
* Content: a generic class factory
*
*
* This is a generic C class factory. All you need to do is implement
* a function called DoCreateInstance that will create an instace of
* your object.
*
* GP_ stands for "General Purpose"
*
* History:
* Date By Reason
* ==== == ======
* 10/13/98 jwo Created it.
* 04/11/00 rodtoll Added code for redirection for custom builds if registry bit is set
* 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE!
* 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
***************************************************************************/
#include "dxvoicepch.h"
HRESULT DVT_Create(LPDIRECTVOICESETUPOBJECT *piDVT);
HRESULT DVS_Create(LPDIRECTVOICESERVEROBJECT *piDVS);
HRESULT DVC_Create(LPDIRECTVOICECLIENTOBJECT *piDVC);
#define EXP __declspec(dllexport)
class CClassFactory : IClassFactory
{
public:
CClassFactory(CLSID* pclsid) : m_lRefCnt(0), m_clsid(*pclsid) {}
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
STDMETHOD_(ULONG, AddRef)()
{
return InterlockedIncrement(&m_lRefCnt);
}
STDMETHOD_(ULONG, Release)()
{
ULONG l = InterlockedDecrement(&m_lRefCnt);
if (l == 0)
{
delete this;
DecrementObjectCount();
}
return l;
}
STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj);
STDMETHOD(LockServer)(BOOL fLock)
{
if( fLock )
{
InterlockedIncrement( &g_lNumLocks );
}
else
{
InterlockedDecrement( &g_lNumLocks );
}
return S_OK;
}
private:
LONG m_lRefCnt;
CLSID m_clsid;
};
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
*ppvObj = NULL;
if( IsEqualIID(riid, IID_IClassFactory) ||
IsEqualIID(riid, IID_IUnknown))
{
InterlockedIncrement( &m_lRefCnt );
*ppvObj = this;
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CClassFactory::CreateInstance"
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj)
{
HRESULT hr = DV_OK;
if( ppvObj == NULL ||
!DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" );
return DVERR_INVALIDPOINTER;
}
if( pUnkOuter != NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Object does not support aggregation" );
return CLASS_E_NOAGGREGATION;
}
if( IsEqualGUID(riid,IID_IDirectPlayVoiceClient) )
{
hr = DVC_Create((LPDIRECTVOICECLIENTOBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVC_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVC_QueryInterface((LPDIRECTVOICECLIENTOBJECT) *ppvObj, riid, ppvObj);
}
else if( IsEqualGUID(riid,IID_IDirectPlayVoiceServer) )
{
hr = DVS_Create((LPDIRECTVOICESERVEROBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVS_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVS_QueryInterface((LPDIRECTVOICESERVEROBJECT) *ppvObj, riid, ppvObj);
}
else if( IsEqualGUID(riid,IID_IDirectPlayVoiceTest) )
{
hr = DVT_Create((LPDIRECTVOICESETUPOBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVT_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVT_QueryInterface((LPDIRECTVOICESETUPOBJECT) *ppvObj, riid, ppvObj);
}
else if( IsEqualGUID(riid,IID_IUnknown) )
{
if( m_clsid == CLSID_DirectPlayVoice )
{
DPFX(DPFPREP, 0, "Requesting IUnknown through generic CLSID" );
return E_NOINTERFACE;
}
else if( m_clsid == CLSID_DirectPlayVoiceClient )
{
hr = DVC_Create((LPDIRECTVOICECLIENTOBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVC_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVC_QueryInterface((LPDIRECTVOICECLIENTOBJECT) *ppvObj, riid, ppvObj);
}
else if( m_clsid == CLSID_DirectPlayVoiceServer )
{
hr = DVS_Create((LPDIRECTVOICESERVEROBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVS_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVS_QueryInterface((LPDIRECTVOICESERVEROBJECT) *ppvObj, riid, ppvObj);
}
else if( m_clsid == CLSID_DirectPlayVoiceTest )
{
hr = DVT_Create((LPDIRECTVOICESETUPOBJECT *) ppvObj);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "DVT_Create Failed hr=0x%x", hr );
return hr;
}
// get the right interface and bump the refcount
hr = DVT_QueryInterface((LPDIRECTVOICESETUPOBJECT) *ppvObj, riid, ppvObj);
}
else
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unknown interface" );
return E_NOINTERFACE;
}
}
else
{
return E_NOINTERFACE;
}
IncrementObjectCount();
return hr;
}
#ifdef DPLAY_LOADANDCHECKTRUE
typedef HRESULT (WINAPI *PFN_DLLGETCLASSOBJECT)(REFCLSID rclsid,REFIID riid,LPVOID *ppvObj );
typedef HRESULT (WINAPI *PFN_DLLCANUNLOADNOW)(void);
extern HMODULE ghRedirect;
extern PFN_DLLGETCLASSOBJECT pfnGetClassObject;
extern PFN_DLLCANUNLOADNOW pfnDllCanUnLoadNow;
#endif
/*
* DllGetClassObject
*
* Entry point called by COM to get a ClassFactory pointer
*/
STDAPI DllGetClassObject(
REFCLSID rclsid,
REFIID riid,
LPVOID *ppvObj )
{
CClassFactory* pcf;
HRESULT hr;
#ifdef DPLAY_LOADANDCHECKTRUE
if( ghRedirect != NULL )
{
GUID guidCLSID;
if( IsEqualCLSID( rclsid, DPVOICE_CLSID_DPVOICE ) )
{
memcpy( &guidCLSID, &CLSID_DirectPlayVoice, sizeof(GUID) );
}
else
{
memcpy( &guidCLSID, rclsid, sizeof(GUID) );
}
return (*pfnGetClassObject)(&guidCLSID,riid,ppvObj);
}
#endif
*ppvObj = NULL;
/*
* is this our class id?
*/
if( !IsEqualCLSID(rclsid, DPVOICE_CLSID_DPVOICE) &&
!IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceClient) &&
!IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceServer) &&
!IsEqualCLSID(rclsid, CLSID_DirectPlayVoiceTest) )
{
return CLASS_E_CLASSNOTAVAILABLE;
}
/*
* only allow IUnknown and IClassFactory
*/
if( !IsEqualIID( riid, IID_IUnknown ) &&
!IsEqualIID( riid, IID_IClassFactory ) )
{
return E_NOINTERFACE;
}
/*
* create a class factory object
*/
pcf = new CClassFactory((CLSID*)&rclsid);
if( NULL == pcf)
{
return E_OUTOFMEMORY;
}
hr = pcf->QueryInterface( riid, ppvObj );
if( FAILED( hr ) )
{
delete ( pcf );
*ppvObj = NULL;
}
else
{
IncrementObjectCount();
}
return hr;
} /* DllGetClassObject */
/*
* DllCanUnloadNow
*
* Entry point called by COM to see if it is OK to free our DLL
*/
STDAPI DllCanUnloadNow( void )
{
HRESULT hr = S_FALSE;
#ifdef DPLAY_LOADANDCHECKTRUE
if( ghRedirect != NULL )
{
return (*pfnDllCanUnLoadNow)();
}
#endif
if ( (0 == g_lNumObjects) && (0 == g_lNumLocks) )
{
hr = S_OK;
}
return hr;
} /* DllCanUnloadNow */