|
|
/*==========================================================================
* * 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 */
|