/*========================================================================== * * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: dpvcpi.cpp * Content: Base class for providing compression DLL implementation * * History: * Date By Reason * ==== == ====== * 10/27/99 rodtoll Created * 01/21/00 rodtoll Moved error level debug to info * 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE! * 06/27/2001 rodtoll RC2: DPVOICE: DPVACM's DllMain calls into acm -- potential hang * Move global initialization to first object creation ***************************************************************************/ #include #include #include "osind.h" #include "dndbg.h" #include "dpvcp.h" #include "dpvcpi.h" LONG IncrementObjectCount(); LONG DecrementObjectCount(); extern "C" LONG g_lNumLocks; CDPVCPI::CompressionNode *CDPVCPI::s_pcnList = NULL; BOOL CDPVCPI::s_fIsLoaded = FALSE; DWORD CDPVCPI::s_dwNumCompressionTypes = 0; #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CDPVCPI" CDPVCPI::CDPVCPI(): m_lRefCount(0), m_fCritSecInited(FALSE) { } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::InitClass" BOOL CDPVCPI::InitClass() { if (DNInitializeCriticalSection( &m_csLock )) { m_fCritSecInited = TRUE; return TRUE; } else { return FALSE; } } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::I_CreateCompressor" HRESULT CDPVCPI::I_CreateCompressor( DPVCPIOBJECT *This, LPWAVEFORMATEX lpwfxSrcFormat, GUID guidTargetCT, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags ) { return This->pObject->CreateCompressor( This, lpwfxSrcFormat, guidTargetCT, ppCompressor, dwFlags ); } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::I_CreateDeCompressor" HRESULT CDPVCPI::I_CreateDeCompressor( DPVCPIOBJECT *This, GUID guidTargetCT, LPWAVEFORMATEX lpwfxSrcFormat, PDPVCOMPRESSOR *ppCompressor, DWORD dwFlags ) { return This->pObject->CreateDeCompressor( This, guidTargetCT, lpwfxSrcFormat, ppCompressor, dwFlags ); } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::~CDPVCPI" CDPVCPI::~CDPVCPI() { if (m_fCritSecInited) { DNDeleteCriticalSection( &m_csLock ); } } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::DeInitCompressionList" HRESULT CDPVCPI::DeInitCompressionList() { return CN_FreeList(); } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::QueryInterface" HRESULT CDPVCPI::QueryInterface( DPVCPIOBJECT *This, REFIID riid, PVOID *ppvObj ) { HRESULT hr = S_OK; if( ppvObj == NULL || !DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" ); return DVERR_INVALIDPOINTER; } *ppvObj=NULL; DNEnterCriticalSection( &This->pObject->m_csLock ); // hmmm, switch would be cleaner... if( IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDPVCompressionProvider ) ) { *ppvObj = This; This->pObject->AddRef( This ); } else { hr = E_NOINTERFACE; } DNLeaveCriticalSection( &This->pObject->m_csLock ); return hr; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::AddRef" HRESULT CDPVCPI::AddRef( DPVCPIOBJECT *This ) { LONG rc; rc = InterlockedIncrement( &This->pObject->m_lRefCount ); return rc; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::Release" HRESULT CDPVCPI::Release( DPVCPIOBJECT *This ) { LONG rc; if( ( rc = InterlockedDecrement( &This->pObject->m_lRefCount ) ) == 0 ) { DPFX(DPFPREP, DVF_INFOLEVEL, "Destroying object" ); delete This->pObject; delete This; DecrementObjectCount(); } return rc; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::EnumCompressionTypes" HRESULT CDPVCPI::EnumCompressionTypes( DPVCPIOBJECT *This, PVOID pBuffer, PDWORD pdwSize, PDWORD pdwNumElements, DWORD dwFlags ) { if( pdwSize == NULL || !DNVALID_WRITEPTR( pdwSize, sizeof( DWORD ) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer specified for pdwSize" ); return DVERR_INVALIDPOINTER; } if( *pdwSize > 0 && !DNVALID_WRITEPTR( pBuffer, *pdwSize ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer specified for buffer" ); return DVERR_INVALIDPOINTER; } CompressionNode *pcnWalker = s_pcnList; DWORD dwRequiredSize = 0, dwTmp = 0, dwNumElements = 0, dwStringSize = 0; LPBYTE pbDataPtr; DVFULLCOMPRESSIONINFO *pbStructPtr; HRESULT hr; // Walk the list and determine how much space we need while( pcnWalker != NULL ) { hr = CI_GetSize( pcnWalker->pdvfci, &dwTmp ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get size" ); return hr; } dwRequiredSize += dwTmp; pcnWalker = pcnWalker->pcnNext; dwNumElements++; } if( dwRequiredSize > *pdwSize ) { *pdwSize = dwRequiredSize; return DVERR_BUFFERTOOSMALL; } *pdwNumElements = dwNumElements; *pdwSize = dwRequiredSize; pbDataPtr = (LPBYTE) pBuffer; pbStructPtr = (DVFULLCOMPRESSIONINFO *) pBuffer; // Move data pointer to be right after location of pbDataPtr += (dwNumElements*sizeof(DVFULLCOMPRESSIONINFO)); pcnWalker = s_pcnList; while( pcnWalker != NULL ) { memcpy( pbStructPtr, pcnWalker->pdvfci, sizeof( DVFULLCOMPRESSIONINFO ) ); // If there is a name, copy it at the end if( pcnWalker->pdvfci->lpszName != NULL && wcslen( pcnWalker->pdvfci->lpszName ) > 0 ) { dwStringSize = (wcslen( pcnWalker->pdvfci->lpszName )+1)*2; memcpy( pbDataPtr, pcnWalker->pdvfci->lpszName, dwStringSize ); pbStructPtr->lpszName = (wchar_t *) pbDataPtr; pbDataPtr += dwStringSize; } // If there's a description, copy it at the end if( pcnWalker->pdvfci->lpszDescription != NULL && wcslen( pcnWalker->pdvfci->lpszDescription ) > 0 ) { dwStringSize = (wcslen( pcnWalker->pdvfci->lpszDescription)+1)*2; memcpy( pbDataPtr, pcnWalker->pdvfci->lpszDescription, dwStringSize ); pbStructPtr->lpszDescription = (wchar_t *) pbDataPtr; pbDataPtr += dwStringSize; } // If there's a format, copy it at the end if( pcnWalker->pdvfci->lpwfxFormat != NULL ) { dwStringSize = sizeof( WAVEFORMATEX ) + pcnWalker->pdvfci->lpwfxFormat->cbSize; memcpy( pbDataPtr, pcnWalker->pdvfci->lpwfxFormat, dwStringSize ); pbStructPtr->lpwfxFormat = (LPWAVEFORMATEX) pbDataPtr; pbDataPtr += dwStringSize; } pbStructPtr ++; pcnWalker = pcnWalker->pcnNext; } return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::IsCompressionSupported" HRESULT CDPVCPI::IsCompressionSupported( DPVCPIOBJECT *This, GUID guidCT ) { DVFULLCOMPRESSIONINFO *pdvfci; if( !FAILED( CN_Get( guidCT, &pdvfci ) ) ) { return DV_OK; } else { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid CT specified" ); return DVERR_COMPRESSIONNOTSUPPORTED; } } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::GetCompressionInfo" HRESULT CDPVCPI::GetCompressionInfo( DPVCPIOBJECT *This, GUID guidCT, PVOID pBuffer, PDWORD pdwSize ) { DVFULLCOMPRESSIONINFO *pdvfci; if( pdwSize == NULL || !DNVALID_WRITEPTR( pdwSize, sizeof( DWORD ) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer specified for pdwSize" ); return DVERR_INVALIDPOINTER; } if( *pdwSize > 0 && !DNVALID_WRITEPTR( pBuffer, *pdwSize ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer specified for buffer" ); return DVERR_INVALIDPOINTER; } if( FAILED( CN_Get( guidCT, &pdvfci ) ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid CT specified" ); return DVERR_COMPRESSIONNOTSUPPORTED; } else { DWORD dwSize; HRESULT hr; LPBYTE pbTmp; DWORD dwStringSize; DVFULLCOMPRESSIONINFO *pTmpInfo; hr = CI_GetSize( pdvfci, &dwSize ); if( FAILED( hr ) ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get size of ci" ); return hr; } if( dwSize > *pdwSize ) { *pdwSize = dwSize; DPFX(DPFPREP, DVF_WARNINGLEVEL, "Buffer too small" ); return DVERR_BUFFERTOOSMALL; } *pdwSize = dwSize; memcpy( pBuffer, pdvfci, sizeof( DVFULLCOMPRESSIONINFO ) ); pbTmp = (LPBYTE) pBuffer; pTmpInfo = (DVFULLCOMPRESSIONINFO *) pBuffer; pbTmp += sizeof( DVFULLCOMPRESSIONINFO ); // If there is a name if( pdvfci->lpszName != NULL && wcslen( pdvfci->lpszName ) > 0 ) { dwStringSize = (wcslen( pdvfci->lpszName )+1)*2; memcpy( pbTmp, pdvfci->lpszName, dwStringSize ); pTmpInfo->lpszName = (wchar_t *) pbTmp; pbTmp += dwStringSize; } if( pdvfci->lpszDescription != NULL && wcslen( pdvfci->lpszDescription ) > 0 ) { dwStringSize = (wcslen( pdvfci->lpszDescription)+1)*2; memcpy( pbTmp, pdvfci->lpszDescription, dwStringSize ); pTmpInfo->lpszDescription = (wchar_t *) pbTmp; pbTmp += dwStringSize; } if( pdvfci->lpwfxFormat != NULL ) { memcpy( pbTmp, pdvfci->lpwfxFormat, sizeof( WAVEFORMATEX ) + pdvfci->lpwfxFormat->cbSize ); pTmpInfo->lpwfxFormat = (LPWAVEFORMATEX) pbTmp; } return DV_OK; } } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CN_Add" HRESULT CDPVCPI::CN_Add( DVFULLCOMPRESSIONINFO *pdvfci ) { CompressionNode *pcnNewNode = new CompressionNode; if( pcnNewNode == NULL ) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Memory alloc failure" ); return DVERR_OUTOFMEMORY; } pcnNewNode->pcnNext = s_pcnList; pcnNewNode->pdvfci = pdvfci; s_pcnList = pcnNewNode; return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CN_Get" HRESULT CDPVCPI::CN_Get( GUID guidCT, DVFULLCOMPRESSIONINFO **pdvfci ) { CompressionNode *pcnWalker = s_pcnList; *pdvfci = NULL; while( pcnWalker != NULL ) { if( pcnWalker->pdvfci->guidType == guidCT ) { *pdvfci = pcnWalker->pdvfci; return DV_OK; } pcnWalker = pcnWalker->pcnNext; } return DVERR_COMPRESSIONNOTSUPPORTED; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CN_FreeList" void CDPVCPI::CN_FreeItem( CompressionNode *pcNode ) { if( pcNode->pdvfci->lpwfxFormat != NULL ) { delete [] pcNode->pdvfci->lpwfxFormat; } if( pcNode->pdvfci->lpszName != NULL ) { delete [] pcNode->pdvfci->lpszName; } if( pcNode->pdvfci->lpszDescription != NULL ) { delete [] pcNode->pdvfci->lpszDescription; } delete pcNode->pdvfci; delete pcNode; } // Free up the list, deallocating memory. #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CN_FreeList" HRESULT CDPVCPI::CN_FreeList() { CompressionNode *pcnWalker = s_pcnList; CompressionNode *pcnTmp; while( pcnWalker != NULL ) { pcnTmp = pcnWalker; pcnWalker = pcnWalker->pcnNext; CN_FreeItem( pcnTmp ); } s_pcnList = NULL; return DV_OK; } #undef DPF_MODNAME #define DPF_MODNAME "CDPVCPI::CI_GetSize" HRESULT CDPVCPI::CI_GetSize( DVFULLCOMPRESSIONINFO *pdvfci, LPDWORD lpdwSize ) { DWORD dwSize = sizeof( DVFULLCOMPRESSIONINFO ); if( pdvfci->lpwfxFormat != NULL ) { dwSize += sizeof( WAVEFORMATEX ) + pdvfci->lpwfxFormat->cbSize; } if( pdvfci->lpszName != NULL ) { dwSize += ((wcslen( pdvfci->lpszName )+1)*2); } if( pdvfci->lpszDescription != NULL ) { dwSize += ((wcslen( pdvfci->lpszDescription )+1)*2); } *lpdwSize = dwSize; return DV_OK; }