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

444 lines
10 KiB
C++

/*==========================================================================
*
* Copyright (C) 1999, 2000 Microsoft Corporation. All Rights Reserved.
*
* File: dllmain.cpp
* Content: This file contains all of the DLL exports except for DllGetClass / DllCanUnload
* History:
* Date By Reason
* ==== == ======
* 07/05/00 rodtoll Created
* 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE!
* 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h
* 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
* 01/11/2001 rmt MANBUG #48487 - DPLAY: Crashes if CoCreate() isn't called.
* 03/14/2001 rmt WINBUG #342420 - Restore COM emulation layer to operation.
*
***************************************************************************/
#include "dxvoicepch.h"
#ifdef DPLAY_LOADANDCHECKTRUE
HRESULT InitializeRedirectFunctionTable()
HRESULT FreeRedirectFunctionTable()
#endif
DNCRITICAL_SECTION g_csObjectInitGuard;
LONG lInitCount = 0;
// # of objects active in the system
volatile LONG g_lNumObjects = 0;
LONG g_lNumLocks = 0;
#undef DPF_MODNAME
#define DPF_MODNAME "RegisterDefaultSettings"
//
// RegisterDefaultSettings
//
// This function registers the default settings for this module.
//
// For DPVOICE.DLL this is making sure the compression provider sub-key is created.
//
HRESULT RegisterDefaultSettings()
{
CRegistry creg;
if( !creg.Open( HKEY_LOCAL_MACHINE, DPVOICE_REGISTRY_BASE DPVOICE_REGISTRY_CP, FALSE, TRUE ) )
{
return DVERR_GENERIC;
}
else
{
return DV_OK;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "UnRegisterDefaultSettings"
//
// UnRegisterDefaultSettings
//
// This function registers the default settings for this module.
//
// For DPVOICE.DLL this is making sure the compression provider sub-key is created.
//
HRESULT UnRegisterDefaultSettings()
{
CRegistry creg;
if( !creg.Open( HKEY_LOCAL_MACHINE, DPVOICE_REGISTRY_BASE, FALSE, TRUE ) )
{
DPFERR( "Cannot remove compression provider, does not exist" );
}
else
{
if( !creg.DeleteSubKey( &(DPVOICE_REGISTRY_CP)[1] ) )
{
DPFERR( "Cannot remove cp sub-key, could have elements" );
}
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "DllRegisterServer"
HRESULT WINAPI DllRegisterServer()
{
HRESULT hr = S_OK;
BOOL fFailed = FALSE;
if( !CRegistry::Register( L"DirectPlayVoice.Compat.1", L"DirectPlayVoice Object",
L"dpvoice.dll", CLSID_DIRECTPLAYVOICE, L"DirectPlayVoice.Compat") )
{
DPFERR( "Could not register compat object" );
fFailed = TRUE;
}
if( !CRegistry::Register( L"DirectPlayVoice.Server.1", L"DirectPlayVoice Server Object",
L"dpvoice.dll", CLSID_DirectPlayVoiceServer, L"DirectPlayVoice.Server") )
{
DPFERR( "Could not register server object" );
fFailed = TRUE;
}
if( !CRegistry::Register( L"DirectPlayVoice.Client.1", L"DirectPlayVoice Client Object",
L"dpvoice.dll", CLSID_DirectPlayVoiceClient,
L"DirectPlayVoice.Client") )
{
DPFERR( "Could not register client object" );
fFailed = TRUE;
}
if( !CRegistry::Register( L"DirectPlayVoice.Test.1", L"DirectPlayVoice Test Object",
L"dpvoice.dll", CLSID_DirectPlayVoiceTest,
L"DirectPlayVoice.Test") )
{
DPFERR( "Could not register test object" );
fFailed = TRUE;
}
if( FAILED( hr = RegisterDefaultSettings() ) )
{
DPFX(DPFPREP, 0, "Could not register default settings hr = 0x%x", hr );
fFailed = TRUE;
}
if( fFailed )
{
return E_FAIL;
}
else
{
return S_OK;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "DllUnregisterServer"
STDAPI DllUnregisterServer()
{
HRESULT hr = S_OK;
BOOL fFailed = FALSE;
if( !CRegistry::UnRegister(CLSID_DirectPlayVoiceServer) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to unregister server object" );
fFailed = TRUE;
}
if( !CRegistry::UnRegister(CLSID_DIRECTPLAYVOICE) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to unregister compat object" );
fFailed = TRUE;
}
if( !CRegistry::UnRegister(CLSID_DirectPlayVoiceClient) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to unregister client object" );
fFailed = TRUE;
}
if( !CRegistry::UnRegister(CLSID_DirectPlayVoiceTest) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to unregister test object" );
fFailed = TRUE;
}
if( FAILED( hr = UnRegisterDefaultSettings() ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to remove default settings hr=0x%x", hr );
}
if( fFailed )
{
return E_FAIL;
}
else
{
return S_OK;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "DirectPlayVoiceCreate"
HRESULT WINAPI DirectPlayVoiceCreate( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown)
{
GUID clsid;
if( pcIID == NULL ||
!DNVALID_READPTR( pcIID, sizeof( GUID ) ) )
{
DPFX(DPFPREP, 0, "Invalid pointer specified for interface GUID" );
return DVERR_INVALIDPOINTER;
}
if( *pcIID != IID_IDirectPlayVoiceClient &&
*pcIID != IID_IDirectPlayVoiceServer &&
*pcIID != IID_IDirectPlayVoiceTest )
{
DPFX(DPFPREP, 0, "Interface ID is not recognized" );
return DVERR_INVALIDPARAM;
}
if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
{
DPFX(DPFPREP, 0, "Invalid pointer specified to receive interface" );
return DVERR_INVALIDPOINTER;
}
if( pUnknown != NULL )
{
DPFX(DPFPREP, 0, "Aggregation is not supported by this object yet" );
return DVERR_INVALIDPARAM;
}
if( *pcIID == IID_IDirectPlayVoiceClient )
{
clsid = CLSID_DirectPlayVoiceClient;
}
else if( *pcIID == IID_IDirectPlayVoiceServer )
{
clsid = CLSID_DirectPlayVoiceServer;
}
else if( *pcIID == IID_IDirectPlayVoiceTest )
{
clsid = CLSID_DirectPlayVoiceTest;
}
else
{
DPFERR( "Invalid IID specified" );
return E_NOINTERFACE;
}
return COM_CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, *pcIID, ppvInterface, TRUE );
}
#undef DPF_MODNAME
#define DPF_MODNAME "DllMain"
BOOL WINAPI DllMain(
HINSTANCE hDllInst,
DWORD fdwReason,
LPVOID lpvReserved)
{
if( fdwReason == DLL_PROCESS_ATTACH )
{
if( !lInitCount )
{
#ifndef WIN95
SHFusionInitializeFromModule(hDllInst);
#endif
if (!DNOSIndirectionInit())
{
return FALSE;
}
if (!DNInitializeCriticalSection(&g_csObjectInitGuard))
{
DPFX(DPFPREP, 0, "Failed to create CS" );
DNOSIndirectionDeinit();
return FALSE;
}
if (FAILED(COM_Init()))
{
DPFX(DPFPREP, 0, "Failed to Init COM layer" );
DNDeleteCriticalSection(&g_csObjectInitGuard);
DNOSIndirectionDeinit();
return FALSE;
}
if (!DSERRTRACK_Init())
{
DPFX(DPFPREP, 0, "Failed to Init DS error tracking" );
COM_Free();
DNDeleteCriticalSection(&g_csObjectInitGuard);
DNOSIndirectionDeinit();
return FALSE;
}
#if defined(DEBUG) || defined(DBG)
Instrument_Core_Init();
#endif
#ifdef DPLAY_LOADANDCHECKTRUE
InitializeRedirectFunctionTable();
#endif
InterlockedIncrement( &lInitCount );
PERF_Initialize();
}
}
else if( fdwReason == DLL_PROCESS_DETACH )
{
InterlockedDecrement( &lInitCount );
if( lInitCount == 0 )
{
DSERRTRACK_UnInit();
DPFX(DPFPREP, DVF_INFOLEVEL, ">>>>>>>>>>>>>>>> DPF UNINITED <<<<<<<<<<<<<<<" );
#ifdef DPLAY_LOADANDCHECKTRUE
FreeRedirectFunctionTable();
#endif
COM_Free();
PERF_DeInitialize();
DNDeleteCriticalSection(&g_csObjectInitGuard);
// This must be called after all DNDeleteCriticalSection calls are done
DNOSIndirectionDeinit();
// Check to ensure we're not being unloaded with objects active
if( g_lNumObjects != 0 || g_lNumLocks != 0 )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "=========================================================================" );
DPFX(DPFPREP, DVF_ERRORLEVEL, "DPVOICE.DLL is unloading with %i objects and %i locks still open. This is an ERROR. ", g_lNumObjects, g_lNumLocks );
DPFX(DPFPREP, DVF_ERRORLEVEL, "You must release all DirectPlayVoice objects before exiting your process." );
DPFX(DPFPREP, DVF_ERRORLEVEL, "=========================================================================" );
DNASSERT( FALSE );
}
#ifndef WIN95
SHFusionUninitialize();
#endif
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// SUPPORT FUNCTIONS FOR STANDALONE DLL
#ifdef DPLAY_LOADANDCHECKTRUE
typedef HRESULT (WINAPI *PFN_DLLGETCLASSOBJECT)(REFCLSID rclsid,REFIID riid,LPVOID *ppvObj );
typedef HRESULT (WINAPI *PFN_DLLCANUNLOADNOW)(void);
extern "C" {
HMODULE ghRedirect = NULL;
PFN_DLLGETCLASSOBJECT pfnGetClassObject = NULL;
PFN_DLLCANUNLOADNOW pfnDllCanUnLoadNow = NULL;
};
#undef DPF_MODNAME
#define DPF_MODNAME "CheckForPrivateBit"
BOOL CheckForPrivateBit( DWORD dwBit )
{
CRegistry creg;
DWORD dwValue;
if( !creg.Open( DPLAY_LOADTREE_REGTREE, DPLAY_LOADTRUE_REGPATH, TRUE, FALSE ) )
{
return FALSE;
}
if( !creg.ReadDWORD( DPLAY_LOADTRUE_REGKEY, dwValue ) )
{
return FALSE;
}
if( dwValue & dwBit )
{
return TRUE;
}
else
{
return FALSE;
}
}
HRESULT InitializeRedirectFunctionTable()
{
LONG lLastError;
if( CheckForPrivateBit( DPLAY_LOADTRUE_BIT ) )
{
ghRedirect = LoadLibrary( "dpvoice.dll" );
if( ghRedirect == NULL )
{
lLastError = GetLastError();
DPFX(DPFPREP, 0, "Could not load dplayx.dll error = 0x%x", lLastError );
return DPERR_GENERIC;
}
pfnGetClassObject = (PFN_DLLGETCLASSOBJECT) GetProcAddress( ghRedirect, "DllGetClassObject" );
pfnDllCanUnLoadNow = (PFN_DLLCANUNLOADNOW) GetProcAddress( ghRedirect, "DllCanUnloadNow" );
}
return DP_OK;
}
HRESULT FreeRedirectFunctionTable()
{
if( ghRedirect != NULL )
FreeLibrary( ghRedirect );
return DP_OK;
}
#endif
LONG DecrementObjectCount()
{
LONG lNewValue;
DNEnterCriticalSection( &g_csObjectInitGuard );
g_lNumObjects--;
lNewValue = g_lNumObjects;
if( g_lNumObjects == 0 )
{
CDirectVoiceEngine::Shutdown();
}
DNLeaveCriticalSection( &g_csObjectInitGuard );
return lNewValue;
}
LONG IncrementObjectCount()
{
LONG lNewValue;
DNEnterCriticalSection( &g_csObjectInitGuard );
g_lNumObjects++;
lNewValue = g_lNumObjects;
if( g_lNumObjects == 1 )
{
CDirectVoiceEngine::Startup(DPVOICE_REGISTRY_BASE);
}
DNLeaveCriticalSection( &g_csObjectInitGuard );
return lNewValue;
}