/*========================================================================== * * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: dvcdb.cpp * Content: * This module contains the implementation of the compression * subsystem and the associated utility functions. * * History: * Date By Reason * ==== == ====== * 08/29/99 rodtoll Created * 09/01/99 rodtoll Updated to add checks for valid read/write pointers * 09/07/99 rodtoll Removed bad assert and added dpf_modnames * Removed Create flag on registry opens * 09/10/99 rodtoll dwFlags check on call to DVCDB_CopyCompress... * 09/14/99 rodtoll Minor bugfix in compression info copy * 09/21/99 rodtoll Added OSInd and fixed memory leak * 10/07/99 rodtoll Added stubs for supporting new codecs * rodtoll Updated to use Unicode * 10/15/99 rodtoll Plugged some memory leaks * 10/28/99 rodtoll Updated to use new compression providers * 10/29/99 rodtoll Bug #113726 - Integrate Voxware Codecs, updating to use new * pluggable codec architecture. * 11/22/99 rodtoll Removed false error message when loading compression types * 12/16/99 rodtoll Removed asserts (which were not needed) exposed by compression * provider changes. * 02/10/2000 rodtoll Fixed crash if invalid registry entries are present. * 03/03/2000 rodtoll Updated to handle alternative gamevoice build. * 03/16/2000 rodtoll Updated converter create to check and return error code * 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k w/o Admin * 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs * 06/28/2000 rodtoll Prefix Bug #38022 * 08/28/2000 masonb Voice Merge: Removed OSAL_* and dvosal.h, added STR_* and strutils.h * 08/31/2000 rodtoll Prefix Bug #171840 * 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash * ***************************************************************************/ #include "dxvutilspch.h" #undef DPF_SUBCOMP #define DPF_SUBCOMP DN_SUBCOMP_VOICE struct DVCDBProvider { GUID guidClassID; PDVFULLCOMPRESSIONINFO pInfo; DWORD dwNumElements; DVCDBProvider *pNext; }; DVCDBProvider *g_dvcdbProviderList = NULL; #define REGISTRY_CDB_FORMAT L"Format" #define REGISTRY_WAVEFORMAT_RATE L"Rate" #define REGISTRY_WAVEFORMAT_BITS L"Bits" #define REGISTRY_WAVEFORMAT_CHANNELS L"Channels" #define REGISTRY_WAVEFORMAT_TAG L"Tag" #define REGISTRY_WAVEFORMAT_AVGPERSEC L"AvgPerSec" #define REGISTRY_WAVEFORMAT_BLOCKALIGN L"BlockAlign" #define REGISTRY_WAVEFORMAT_CBSIZE L"cbsize" #define REGISTRY_WAVEFORMAT_CBDATA L"cbdata" #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_CalcUnCompressedFrameSize" DWORD DVCDB_CalcUnCompressedFrameSize( const DVFULLCOMPRESSIONINFO* lpdvInfo, const WAVEFORMATEX* lpwfxFormat ) { DWORD frameSize; switch( lpwfxFormat->nSamplesPerSec ) { case 8000: frameSize = lpdvInfo->dwFrame8Khz; break; case 11025: frameSize = lpdvInfo->dwFrame11Khz; break; case 22050: frameSize = lpdvInfo->dwFrame22Khz; break; case 44100: frameSize = lpdvInfo->dwFrame44Khz; break; default: return 0; } if( lpwfxFormat->wBitsPerSample == 16 ) frameSize *= 2; frameSize *= lpwfxFormat->nChannels; return frameSize; } #undef DPF_MODNAME #define DPF_MODNAME "CREG_ReadAndAllocWaveFormatEx" HRESULT CREG_ReadAndAllocWaveFormatEx( HKEY hkeyReg, LPCWSTR path, LPWAVEFORMATEX *lpwfxFormat ) { CRegistry waveKey; if( !waveKey.Open( hkeyReg, path, TRUE, FALSE ) ) { return E_FAIL; } DWORD dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_CBSIZE, &dwTmp ) ) { return E_FAIL; } *lpwfxFormat = (LPWAVEFORMATEX) new BYTE[dwTmp+sizeof(WAVEFORMATEX)]; LPWAVEFORMATEX tmpFormat = *lpwfxFormat; if( tmpFormat == NULL ) { return E_OUTOFMEMORY; } tmpFormat->cbSize = (BYTE) dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_RATE, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->nSamplesPerSec = dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_BITS, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->wBitsPerSample = (WORD) dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_CHANNELS, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->nChannels = (INT) dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_TAG, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->wFormatTag = (WORD) dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_AVGPERSEC, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->nAvgBytesPerSec = (INT) dwTmp; if( !waveKey.ReadDWORD( REGISTRY_WAVEFORMAT_BLOCKALIGN, &dwTmp ) ) { goto READ_FAILURE; } tmpFormat->nBlockAlign = (INT) dwTmp; dwTmp = tmpFormat->cbSize; if( !waveKey.ReadBlob( REGISTRY_WAVEFORMAT_CBDATA, (LPBYTE) &tmpFormat[1], &dwTmp ) ) { DPFX(DPFPREP, 0, "Error reading waveformat blob" ); goto READ_FAILURE; } return S_OK; READ_FAILURE: delete [] *lpwfxFormat; *lpwfxFormat = NULL; return E_FAIL; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_LoadCompressionInfo" HRESULT DVCDB_LoadCompressionInfo( const WCHAR *swzBaseRegistryPath ) { CRegistry mainKey, subKey; LPWSTR keyName = NULL; DWORD dwIndex = 0; DWORD dwSize = 0; HRESULT hr; PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL; DVCDBProvider *pNewProvider = NULL; WCHAR wszPath[_MAX_PATH]; if( swzBaseRegistryPath == NULL ) { DPFX(DPFPREP, 0, "INTERNAL ERROR!" ); return E_FAIL; } wcscpy( wszPath, swzBaseRegistryPath ); wcscat( wszPath, DPVOICE_REGISTRY_CP ); if( !mainKey.Open( HKEY_LOCAL_MACHINE, wszPath, TRUE, FALSE ) ) { DPFX(DPFPREP, 0, "Error reading compression providers from the registry. Path doesn't exist" ); return E_FAIL; } dwIndex = 0; keyName = NULL; dwSize = 0; LPSTR lpstrKeyName = NULL; GUID guidCP; // Enumerate the subkeys at this point in the tree while( 1 ) { dwSize = 0; if( !mainKey.EnumKeys( keyName, &dwSize, dwIndex ) ) { if( dwSize == 0 ) { DPFX(DPFPREP, DVF_INFOLEVEL, "End of provider list" ); break; } if( keyName != NULL ) { delete [] keyName; } keyName = new wchar_t[dwSize]; } if( !mainKey.EnumKeys( keyName, &dwSize, dwIndex ) ) { delete [] keyName; break; } if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" ); break; } DPFX(DPFPREP, DVF_INFOLEVEL, "Reading provider: %hs", lpstrKeyName ); if( !subKey.Open( mainKey, keyName, TRUE, FALSE ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error reading provider: %hs", lpstrKeyName ); goto SKIP_TO_NEXT; } delete [] keyName; keyName = NULL; dwSize = 0; // Read the GUID from the default key if( !subKey.ReadGUID( L"", &guidCP ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to read the provider's GUID" ); goto SKIP_TO_NEXT; } // Attempt to create the provider hr = COM_CoCreateInstance( guidCP , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider, FALSE ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr ); goto SKIP_TO_NEXT; } // Build a record for the provider pNewProvider = new DVCDBProvider; if( pNewProvider == NULL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory" ); goto SKIP_TO_NEXT; } pNewProvider->guidClassID = guidCP; pNewProvider->pInfo = NULL; pNewProvider->dwNumElements = 0; dwSize = 0; // GetCompression Info for the provider hr = pCompressionProvider->EnumCompressionTypes( pNewProvider->pInfo, &dwSize, &pNewProvider->dwNumElements, 0 ); if( hr != DVERR_BUFFERTOOSMALL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get compression info for provider: %hs", lpstrKeyName ); goto SKIP_TO_NEXT; } pNewProvider->pInfo = (DVFULLCOMPRESSIONINFO *) new BYTE[dwSize]; if( pNewProvider->pInfo == NULL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Out of memory" ); goto SKIP_TO_NEXT; } hr = pCompressionProvider->EnumCompressionTypes( pNewProvider->pInfo, &dwSize, &pNewProvider->dwNumElements, 0 ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get compression info for %hs hr=0x%x", lpstrKeyName, hr ); goto SKIP_TO_NEXT; } // Add it to the list pNewProvider->pNext = g_dvcdbProviderList; g_dvcdbProviderList = pNewProvider; pNewProvider = NULL; SKIP_TO_NEXT: if( pCompressionProvider != NULL ) { pCompressionProvider->Release(); pCompressionProvider = NULL; } if( pNewProvider != NULL ) { delete pNewProvider; pNewProvider = NULL; } if( lpstrKeyName != NULL ) delete [] lpstrKeyName; if( keyName != NULL ) delete [] keyName; lpstrKeyName = NULL; keyName = NULL; dwSize = 0; dwIndex++; continue; } if( lpstrKeyName != NULL ) delete [] lpstrKeyName; if( keyName != NULL ) delete [] keyName; return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_FreeCompressionInfo" HRESULT DVCDB_FreeCompressionInfo() { DVCDBProvider *pTmpProvider, *pTmpNext; if( g_dvcdbProviderList == NULL ) return DV_OK; pTmpProvider = g_dvcdbProviderList; while( pTmpProvider != NULL ) { pTmpNext = pTmpProvider->pNext; delete [] pTmpProvider->pInfo; delete pTmpProvider; pTmpProvider = pTmpNext; } g_dvcdbProviderList = NULL; return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_GetCompressionClassID" HRESULT DVCDB_GetCompressionClassID( const GUID& guidCT, GUID* pguidClass ) { DVCDBProvider *pTmpProvider; DWORD dwIndex; pTmpProvider = g_dvcdbProviderList; while( pTmpProvider != NULL ) { for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ ) { if( pTmpProvider->pInfo[dwIndex].guidType == guidCT ) { *pguidClass = pTmpProvider->guidClassID; return DV_OK; } } pTmpProvider = pTmpProvider->pNext; } return DVERR_COMPRESSIONNOTSUPPORTED; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_GetCompressionInfo" HRESULT DVCDB_GetCompressionInfo( const GUID &guidType, PDVFULLCOMPRESSIONINFO *lpdvfCompressionInfo ) { DVCDBProvider *pTmpProvider; DWORD dwIndex; pTmpProvider = g_dvcdbProviderList; while( pTmpProvider != NULL ) { for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ ) { if( pTmpProvider->pInfo[dwIndex].guidType == guidType ) { *lpdvfCompressionInfo = &pTmpProvider->pInfo[dwIndex]; return DV_OK; } } pTmpProvider = pTmpProvider->pNext; } return DVERR_COMPRESSIONNOTSUPPORTED; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_CreateConverter" HRESULT DVCDB_CreateConverter( WAVEFORMATEX *pwfxSrcFormat, const GUID &guidTarget, PDPVCOMPRESSOR *pConverter ) { HRESULT hr; GUID guidProvider; PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL; hr = DVCDB_GetCompressionClassID( guidTarget, &guidProvider ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Requested compression type is not supported, hr=0x%x", hr ); return hr; } hr = COM_CoCreateInstance( guidProvider , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider, FALSE ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr ); return DVERR_COMPRESSIONNOTSUPPORTED; } hr = pCompressionProvider->CreateCompressor( pwfxSrcFormat, guidTarget, pConverter, 0 ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error creating compressor hr=0x%x", hr ); return hr; } pCompressionProvider->Release(); return hr; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_CreateConverter" HRESULT DVCDB_CreateConverter( const GUID &guidSrc, WAVEFORMATEX *pwfxTarget, PDPVCOMPRESSOR *pConverter ) { HRESULT hr; GUID guidProvider; PDPVCOMPRESSIONPROVIDER pCompressionProvider = NULL; hr = DVCDB_GetCompressionClassID( guidSrc, &guidProvider ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Requested compression type is not supported, hr=0x%x", hr ); return hr; } hr = COM_CoCreateInstance( guidProvider , NULL, CLSCTX_INPROC_SERVER, IID_IDPVCompressionProvider, (void **) &pCompressionProvider, FALSE ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "FAILED to create 0x%x\n", hr ); return DVERR_COMPRESSIONNOTSUPPORTED; } hr = pCompressionProvider->CreateDeCompressor( guidSrc, pwfxTarget, pConverter, 0 ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Error creating compressor hr=0x%x", hr ); return hr; } pCompressionProvider->Release(); return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_CopyCompressionArrayToBuffer" HRESULT DVCDB_CopyCompressionArrayToBuffer( LPVOID lpBuffer, LPDWORD lpdwSize, LPDWORD lpdwNumElements, DWORD dwFlags ) { if( lpdwNumElements == NULL || lpdwSize == NULL || !DNVALID_READPTR(lpdwNumElements,sizeof(DWORD)) || !DNVALID_READPTR(lpdwSize,sizeof(DWORD)) ) { return E_POINTER; } if( dwFlags != 0 ) { return DVERR_INVALIDFLAGS; } DWORD dwIndex, dwReadIndex; DWORD dwRequiredSize = 0; DWORD dwTmpSize; LPDVCOMPRESSIONINFO lpdvTargetList; LPBYTE lpbExtraLoc = (LPBYTE) lpBuffer; *lpdwNumElements = 0; DVCDBProvider *pTmpProvider; pTmpProvider = g_dvcdbProviderList; while( pTmpProvider != NULL ) { for( dwIndex = 0; dwIndex < pTmpProvider->dwNumElements; dwIndex++ ) { dwRequiredSize += DVCDB_GetCompressionInfoSize( (LPDVCOMPRESSIONINFO) &pTmpProvider->pInfo[dwIndex] ); (*lpdwNumElements)++; } pTmpProvider = pTmpProvider->pNext; } if( *lpdwSize < dwRequiredSize ) { *lpdwSize = dwRequiredSize; return DVERR_BUFFERTOOSMALL; } *lpdwSize = dwRequiredSize; if( lpBuffer == NULL || !DNVALID_WRITEPTR(lpBuffer,dwRequiredSize) ) { return E_POINTER; } lpbExtraLoc += (*lpdwNumElements)*sizeof(DVCOMPRESSIONINFO); lpdvTargetList = (LPDVCOMPRESSIONINFO) lpBuffer; pTmpProvider = g_dvcdbProviderList; dwIndex = 0; while( pTmpProvider != NULL ) { for( dwReadIndex = 0; dwReadIndex < pTmpProvider->dwNumElements; dwReadIndex++, dwIndex++ ) { memcpy( &lpdvTargetList[dwIndex], &pTmpProvider->pInfo[dwReadIndex], sizeof(DVCOMPRESSIONINFO) ); if( pTmpProvider->pInfo[dwReadIndex].lpszDescription != NULL ) { dwTmpSize = (wcslen( pTmpProvider->pInfo[dwReadIndex].lpszDescription )*2)+2; memcpy( lpbExtraLoc, pTmpProvider->pInfo[dwReadIndex].lpszDescription, dwTmpSize ); lpdvTargetList[dwIndex].lpszDescription = (LPWSTR) lpbExtraLoc; lpbExtraLoc += dwTmpSize; } if( pTmpProvider->pInfo[dwReadIndex].lpszName != NULL ) { dwTmpSize = (wcslen( pTmpProvider->pInfo[dwReadIndex].lpszName )*2)+2; memcpy( lpbExtraLoc, pTmpProvider->pInfo[dwReadIndex].lpszName, dwTmpSize ); lpdvTargetList[dwIndex].lpszName = (LPWSTR) lpbExtraLoc; lpbExtraLoc += dwTmpSize; } } pTmpProvider = pTmpProvider->pNext; } return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "DVCDB_GetCompressionInfoSize" DWORD DVCDB_GetCompressionInfoSize( LPDVCOMPRESSIONINFO lpdvCompressionInfo ) { DNASSERT( lpdvCompressionInfo != NULL ); DWORD dwSize; dwSize = sizeof( DVCOMPRESSIONINFO ); if( lpdvCompressionInfo->lpszDescription != NULL ) { dwSize += (wcslen( lpdvCompressionInfo->lpszDescription )*2)+2; } if( lpdvCompressionInfo->lpszName != NULL ) { dwSize += (wcslen( lpdvCompressionInfo->lpszName)*2)+2; } return dwSize; }