/*========================================================================== * * 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. * 02/28/2002 rodtoll WINBUG #550124 - SECURITY: DPVOICE: Shared memory region with NULL DACL * - Remove performance statistics dumping to shared memory * ***************************************************************************/ #include "dxvoicepch.h" 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 !defined(DBG) || !defined( DIRECTX_REDIST ) #define DPVOICE_FILENAME_DPVOICE L"dpvoice.dll" #else // For redist debug builds we append a 'd' to the name to allow both debug and retail to be installed on the system #define DPVOICE_FILENAME_DPVOICE L"dpvoiced.dll" #endif // !defined(DBG) || !defined( DIRECTX_REDIST ) if( !CRegistry::Register( L"DirectPlayVoice.Compat.1", L"DirectPlayVoice Object", DPVOICE_FILENAME_DPVOICE, &CLSID_DIRECTPLAYVOICE, L"DirectPlayVoice.Compat") ) { DPFERR( "Could not register compat object" ); fFailed = TRUE; } if( !CRegistry::Register( L"DirectPlayVoice.Server.1", L"DirectPlayVoice Server Object", DPVOICE_FILENAME_DPVOICE, &CLSID_DirectPlayVoiceServer, L"DirectPlayVoice.Server") ) { DPFERR( "Could not register server object" ); fFailed = TRUE; } if( !CRegistry::Register( L"DirectPlayVoice.Client.1", L"DirectPlayVoice Client Object", DPVOICE_FILENAME_DPVOICE, &CLSID_DirectPlayVoiceClient, L"DirectPlayVoice.Client") ) { DPFERR( "Could not register client object" ); fFailed = TRUE; } if( !CRegistry::Register( L"DirectPlayVoice.Test.1", L"DirectPlayVoice Test Object", DPVOICE_FILENAME_DPVOICE, &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(0)) { 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 InterlockedIncrement( &lInitCount ); } } else if( fdwReason == DLL_PROCESS_DETACH ) { InterlockedDecrement( &lInitCount ); if( lInitCount == 0 ) { DSERRTRACK_UnInit(); DPFX(DPFPREP, DVF_INFOLEVEL, ">>>>>>>>>>>>>>>> DPF UNINITED <<<<<<<<<<<<<<<" ); COM_Free(); 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; } 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; }