444 lines
10 KiB
C++
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;
|
||
|
}
|