Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

545 lines
16 KiB

/*==========================================================================;
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: dpvacmi.cpp
* Content: Definition of object which implements ACM compression provider interface
*
* History:
* Date By Reason
* =========== =========== ====================
* 10/27/99 rodtoll created
* 12/16/99 rodtoll Bug #123250 - Insert proper names/descriptions for codecs
* Codec names now based on resource entries for format and
* names are constructed using ACM names + bitrate
* 01/20/00 rodtoll Removed dplay reference (DPERR_OUTOFMEMORY)
* 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
* 03/16/2000 rodtoll Fixed problem w/GameVoice build -- always loaded dvoice provider
* 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k on non-admin account
* 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
* 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h added STR_* and strutils.h
* 08/31/2000 rodtoll Whistler Bug #171837, 171838 - Prefix Bug
* 04/22/2001 rodtoll MANBUG #50058 DPVOICE: VoicePosition: No sound for couple of seconds when
* positioning bars moved. Increased # of frames / buffer value for codecs.
* 02/25/2002 rodtoll WINBUG #550063: Potential DOS by forcing server to allocate excessive amounts of memory.
* Reduced upper bounds on individual sub-queues to 32 messages from 64.
* rodtoll WINBUG #552283: Reduce attack surface / dead code removal
* Removed ability to load arbitrary ACM codecs.
*
***************************************************************************/
#include "dpvacmpch.h"
#define DPVACM_NUM_DEFAULT_TYPES 4
BYTE abTrueSpeechData[] = {
0x01, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
BYTE abGSMData[] = {
0x40, 0x01
};
BYTE abADPCMData[] = {
0xF4, 0x01, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x02, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x40, 0x00, 0xF0, 0x00, 0x00, 0x00,
0xCC, 0x01, 0x30, 0xFF, 0x88, 0x01, 0x18, 0xFF
};
VOID *s_pvExtras[DPVACM_NUM_DEFAULT_TYPES] = {
&abTrueSpeechData,
&abGSMData,
&abADPCMData,
NULL
};
WAVEFORMATEX s_wfxFormats[DPVACM_NUM_DEFAULT_TYPES] =
{
// Tag, Chan, SamS, Avg, Align, Bits, size
{ 34, 0x01, 8000, 1067, 32, 1, sizeof( abTrueSpeechData ) },
{ 49, 0x01, 8000, 1625, 65, 0, sizeof( abGSMData ) },
{ 2, 0x01, 8000, 4096, 256, 4, sizeof( abADPCMData ) },
{ 1, 0x01, 8000, 8000, 1, 8, 0 }
};
DVFULLCOMPRESSIONINFO s_dvInfoDefault[DPVACM_NUM_DEFAULT_TYPES] =
{
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_TRUESPEECH.Data1, DPVCTGUID_TRUESPEECH.Data2, DPVCTGUID_TRUESPEECH.Data3,
DPVCTGUID_TRUESPEECH.Data4[0], DPVCTGUID_TRUESPEECH.Data4[1], DPVCTGUID_TRUESPEECH.Data4[2], DPVCTGUID_TRUESPEECH.Data4[3],
DPVCTGUID_TRUESPEECH.Data4[4], DPVCTGUID_TRUESPEECH.Data4[5], DPVCTGUID_TRUESPEECH.Data4[6], DPVCTGUID_TRUESPEECH.Data4[7],
NULL, NULL, 0, 8536, NULL, 12, 1, 90, 96, 720, 993, 1986, 3972, 32, 22, 10, 1, 0, 0 },
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_GSM.Data1, DPVCTGUID_GSM.Data2, DPVCTGUID_GSM.Data3,
DPVCTGUID_GSM.Data4[0], DPVCTGUID_GSM.Data4[1], DPVCTGUID_GSM.Data4[2], DPVCTGUID_GSM.Data4[3],
DPVCTGUID_GSM.Data4[4], DPVCTGUID_GSM.Data4[5], DPVCTGUID_GSM.Data4[6], DPVCTGUID_GSM.Data4[7],
NULL, NULL, 0, 13000, NULL, 13, 1, 80, 130, 640, 882, 1764, 3528, 32, 24, 10, 1, 0, 0 },
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_ADPCM.Data1, DPVCTGUID_ADPCM.Data2, DPVCTGUID_ADPCM.Data3,
DPVCTGUID_ADPCM.Data4[0], DPVCTGUID_ADPCM.Data4[1], DPVCTGUID_ADPCM.Data4[2], DPVCTGUID_ADPCM.Data4[3],
DPVCTGUID_ADPCM.Data4[4], DPVCTGUID_ADPCM.Data4[5], DPVCTGUID_ADPCM.Data4[6], DPVCTGUID_ADPCM.Data4[7],
NULL, NULL, 0, 32768, NULL, 15, 1, 63, 256, 500, 690, 1380, 2760, 32, 31, 10, 1, 0, 0 },
{ sizeof( DVFULLCOMPRESSIONINFO ), DPVCTGUID_NONE.Data1, DPVCTGUID_NONE.Data2, DPVCTGUID_NONE.Data3,
DPVCTGUID_NONE.Data4[0], DPVCTGUID_NONE.Data4[1], DPVCTGUID_NONE.Data4[2], DPVCTGUID_NONE.Data4[3],
DPVCTGUID_NONE.Data4[4], DPVCTGUID_NONE.Data4[5], DPVCTGUID_NONE.Data4[6], DPVCTGUID_NONE.Data4[7],
NULL, NULL, 0, 64000, NULL, 20, 1, 50, 394, 394, 543, 1086, 2172, 32, 39, 10, 1, 0, 0 }
};
const wchar_t * const s_wszInfoNames[DPVACM_NUM_DEFAULT_TYPES] =
{
L"DSP Group Truespeech(TM) (8.000 kHz, 1 Bit, Mono)",
L"GSM 6.10 (8.000 kHz, Mono)",
L"Microsoft ADPCM (8.000 kHz, 4 Bit, Mono)",
L"PCM (8.000 kHz, 8 Bit, Mono"
};
WAVEFORMATEX CDPVACMI::s_wfxInnerFormat= {
WAVE_FORMAT_PCM, 1,8000,16000,2,16,0
};
#define MAX_RESOURCE_STRING_LENGTH 200
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::LoadDefaultTypes"
HRESULT CDPVACMI::LoadDefaultTypes( HINSTANCE hInst )
{
HRESULT hr = DV_OK;
CompressionNode *pNewNode;
CWaveFormat wfxFormat;
for( DWORD dwIndex = 0; dwIndex < DPVACM_NUM_DEFAULT_TYPES; dwIndex++ )
{
pNewNode = new CompressionNode;
if( pNewNode == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory allocation failure" );
return DVERR_OUTOFMEMORY;
}
pNewNode->pdvfci = new DVFULLCOMPRESSIONINFO;
if( pNewNode->pdvfci == NULL )
{
delete pNewNode;
DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory allocation failure" );
return DVERR_OUTOFMEMORY;
}
// Copy main portion
memcpy( pNewNode->pdvfci, &s_dvInfoDefault[dwIndex], sizeof( DVFULLCOMPRESSIONINFO ) );
// Copy the waveformat
hr = wfxFormat.InitializeCPY( &s_wfxFormats[dwIndex], s_pvExtras[dwIndex] );
if( FAILED( hr ) )
{
DPFX(DPFPREP, 0, "Unable to initialize built-in type %d", dwIndex );
CN_FreeItem( pNewNode );
continue;
}
pNewNode->pdvfci->lpwfxFormat = wfxFormat.Disconnect();
DNASSERT( pNewNode->pdvfci->lpwfxFormat );
hr = GetCompressionNameAndDescription( hInst, pNewNode->pdvfci );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error building built-in type: %d hr=0x%x", dwIndex, hr );
DPFX(DPFPREP, DVF_ERRORLEVEL, "Type will not be available" );
CN_FreeItem( pNewNode );
continue;
}
AddEntry( pNewNode );
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::AddEntry"
void CDPVACMI::AddEntry( CompressionNode *pNewNode )
{
CompressionNode *pcNode, *pcPrevNode;
pcPrevNode = NULL;
pcNode = s_pcnList;
// Run the list and ensure an entry doesn't already exist
// If one does, over-ride it with this new one.
while( pcNode )
{
// A node already exists for this type
if( pcNode->pdvfci->guidType == pNewNode->pdvfci->guidType )
{
// We need to drop this count because we increment it below.
s_dwNumCompressionTypes--;
if( pcPrevNode == NULL )
{
s_pcnList = pcNode->pcnNext;
}
else
{
pcPrevNode->pcnNext = pcNode->pcnNext;
}
CN_FreeItem(pcNode);
break;
}
pcPrevNode = pcNode;
pcNode = pcNode->pcnNext;
}
pNewNode->pcnNext = s_pcnList;
s_pcnList = pNewNode;
s_dwNumCompressionTypes++;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::InitCompressionList"
HRESULT CDPVACMI::InitCompressionList( HINSTANCE hInst, const wchar_t *szwRegistryBase )
{
HRESULT hr;
hr = IsPCMConverterAvailable();
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "PCM Converter is disabled hr=0x%x, no ACM compression types are available", hr );
return hr;
}
hr = LoadDefaultTypes( hInst );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load built-in types from registry." );
return E_FAIL;
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::CreateCompressor"
HRESULT CDPVACMI::CreateCompressor( DPVCPIOBJECT *This, LPWAVEFORMATEX lpwfxSrcFormat, GUID guidTargetCT, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags )
{
HRESULT hr;
hr = COM_CoCreateInstance( CLSID_DPVCPACM_CONVERTER, NULL, CLSCTX_INPROC_SERVER, IID_IDPVConverter, (void **) ppCompressor, FALSE );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to create converter, hr = 0x%x", hr );
return hr;
}
hr = (*ppCompressor)->lpVtbl->InitCompress( (*ppCompressor), lpwfxSrcFormat, guidTargetCT );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init compressor, hr = 0x%x", hr );
(*ppCompressor)->lpVtbl->Release((*ppCompressor));
*ppCompressor = NULL;
return hr;
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::CreateDeCompressor"
HRESULT CDPVACMI::CreateDeCompressor( DPVCPIOBJECT *This, GUID guidTargetCT, LPWAVEFORMATEX lpwfxSrcFormat, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags )
{
HRESULT hr;
hr = COM_CoCreateInstance( CLSID_DPVCPACM_CONVERTER, NULL, CLSCTX_INPROC_SERVER, IID_IDPVConverter, (void **) ppCompressor, FALSE );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to create decompressor, hr = 0x%x", hr );
return hr;
}
hr = (*ppCompressor)->lpVtbl->InitDeCompress( (*ppCompressor), guidTargetCT, lpwfxSrcFormat );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed to init decompressor, hr = 0x%x", hr );
(*ppCompressor)->lpVtbl->Release((*ppCompressor));
*ppCompressor = NULL;
return hr;
}
return DV_OK;
}
// # of chars of extra tacked on by description
// This is equivalent to "XXXXXXX.X kbit/s"
#define DVACMCP_EXTRACHARS 80
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::GetDriverNameW"
HRESULT CDPVACMI::GetDriverNameW( HACMDRIVERID hadid, wchar_t *szwDriverName )
{
ACMDRIVERDETAILSW acDriverDetails;
MMRESULT mmr;
memset( &acDriverDetails, 0x00, sizeof( ACMDRIVERDETAILS ) );
acDriverDetails.cbStruct = sizeof( ACMDRIVERDETAILS );
mmr = acmDriverDetailsW( hadid, &acDriverDetails, 0 );
if( mmr != 0 )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get driver details mmr=0x%x", mmr );
return DVERR_COMPRESSIONNOTSUPPORTED;
}
if( acDriverDetails.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Driver is disabled!" );
return DVERR_COMPRESSIONNOTSUPPORTED;
}
wcscpy( szwDriverName, acDriverDetails.szShortName );
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::GetDriverNameA"
HRESULT CDPVACMI::GetDriverNameA( HACMDRIVERID hadid, wchar_t *szwDriverName )
{
ACMDRIVERDETAILSA acDriverDetails;
MMRESULT mmr;
memset( &acDriverDetails, 0x00, sizeof( ACMDRIVERDETAILS ) );
acDriverDetails.cbStruct = sizeof( ACMDRIVERDETAILS );
mmr = acmDriverDetailsA( hadid, &acDriverDetails, 0 );
if( mmr != 0 )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get driver details mmr=0x%x", mmr );
return DVERR_COMPRESSIONNOTSUPPORTED;
}
if( acDriverDetails.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Driver is disabled!" );
return DVERR_COMPRESSIONNOTSUPPORTED;
}
if( FAILED(STR_jkAnsiToWide( szwDriverName, acDriverDetails.szShortName, ACMDRIVERDETAILS_SHORTNAME_CHARS+1 )) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to convert driver name to UNICODE" );
return DVERR_COMPRESSIONNOTSUPPORTED;
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::LoadAndAllocString"
HRESULT CDPVACMI::LoadAndAllocString( HINSTANCE hInstance, UINT uiResourceID, wchar_t **lpswzString )
{
int length;
HRESULT hr;
#ifdef UNICODE
wchar_t wszTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
length = LoadStringW( hInstance, uiResourceID, wszTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
if( length == 0 )
{
hr = GetLastError();
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load resource ID %d error 0x%x", uiResourceID, hr );
*lpswzString = NULL;
return hr;
}
else
{
*lpswzString = new wchar_t[length+1];
if( *lpswzString == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Alloc failure" );
return DVERR_OUTOFMEMORY;
}
wcscpy( *lpswzString, wszTmpBuffer );
return DV_OK;
}
#else
char szTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
length = LoadStringA( hInstance, uiResourceID, szTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
if( length == 0 )
{
hr = GetLastError();
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load resource ID %d error 0x%x", uiResourceID, hr );
*lpswzString = NULL;
return hr;
}
else
{
*lpswzString = new wchar_t[length+1];
if( *lpswzString == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Alloc failure" );
return DVERR_OUTOFMEMORY;
}
if( FAILED(STR_jkAnsiToWide( *lpswzString, szTmpBuffer, length+1 )) )
{
hr = GetLastError();
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to upconvert from ansi to unicode hr=0x%x", hr );
return hr;
}
return DV_OK;
}
#endif // UNICODE
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDPVACMI::GetCompressionNameAndDescription"
HRESULT CDPVACMI::GetCompressionNameAndDescription( HINSTANCE hInst, DVFULLCOMPRESSIONINFO *pdvCompressionInfo )
{
MMRESULT mmr;
HACMSTREAM has = NULL;
HACMDRIVERID acDriverID = NULL;
wchar_t szwDriverName[ACMDRIVERDETAILS_SHORTNAME_CHARS+DVACMCP_EXTRACHARS];
wchar_t szExtraCharsBuild[DVACMCP_EXTRACHARS+1];
wchar_t *szwFormat;
HRESULT hr;
// Description is always NULL
pdvCompressionInfo->lpszDescription = NULL;
// Attempt to open a conversion using the parameters specified.
mmr = acmStreamOpen( &has, NULL, &s_wfxInnerFormat, pdvCompressionInfo->lpwfxFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME );
if( mmr != 0 )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed testing compression type. mmr=0x%x", mmr );
hr = DVERR_COMPRESSIONNOTSUPPORTED;
goto GETINFOERROR;
}
mmr = acmDriverID( (HACMOBJ) has, &acDriverID, 0 );
if( mmr != 0 )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to determine ACM driver for type mmr=0x%x", mmr );
hr = DVERR_COMPRESSIONNOTSUPPORTED;
goto GETINFOERROR;
}
#ifdef UNICODE
hr = GetDriverNameW( acDriverID, szwDriverName );
#else
hr = GetDriverNameA( acDriverID, szwDriverName );
#endif
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Failed getting driver name hr=0x%x", hr );
goto GETINFOERROR;
}
if( pdvCompressionInfo->dwMaxBitsPerSecond % 1000 == 0 )
{
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_KBITSPERSEC, &szwFormat ) ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format for name" );
goto GETINFOERROR;
}
swprintf( szExtraCharsBuild, szwFormat, pdvCompressionInfo->dwMaxBitsPerSecond / 1000 );
delete [] szwFormat;
}
else
{
DWORD dwMajor, dwFraction;
dwMajor = pdvCompressionInfo->dwMaxBitsPerSecond / 1000;
dwFraction = (pdvCompressionInfo->dwMaxBitsPerSecond % 1000) / 100;
if( (pdvCompressionInfo->dwMaxBitsPerSecond % 1000) > 500 )
{
dwFraction++;
}
if( dwFraction > 10 )
{
dwMajor++;
dwFraction -= 10;
}
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_KBITSPERSEC_FULL, &szwFormat ) ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format for name (full)" );
goto GETINFOERROR;
}
swprintf( szExtraCharsBuild, szwFormat, dwMajor, dwFraction );
delete [] szwFormat;
}
if( FAILED( LoadAndAllocString( hInst, IDS_CODECNAME_FORMAT, &szwFormat ) ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to load format" );
goto GETINFOERROR;
}
pdvCompressionInfo->lpszName = new wchar_t[wcslen(szwDriverName)+wcslen(szwFormat)+wcslen(szExtraCharsBuild)+1];
if( pdvCompressionInfo->lpszName == NULL )
{
delete [] szwFormat;
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to allocate space for compression name" );
hr = DVERR_OUTOFMEMORY;
goto GETINFOERROR;
}
swprintf( pdvCompressionInfo->lpszName, szwFormat, szwDriverName, szExtraCharsBuild );
acmStreamClose( has, 0 );
if( szwFormat != NULL )
delete [] szwFormat;
return DV_OK;
GETINFOERROR:
if( has != NULL )
{
acmStreamClose( has, 0 );
}
return hr;
}