316 lines
7.2 KiB
C++
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 */
|
||
|
|