2025-11-28 00:35:46 +09:00

453 lines
12 KiB
C++

//*****************************************************************************
//
// Microsoft Windows Media
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// FileName: ExtensionData.cpp
//
// Abstract: Implementation of the CExtensionData class
//
//*****************************************************************************
//////////////////////////////////////////////////////////////////////
// This file contains the following helper classes used to retrieve and
// display data unit extensions for all streams in the profile :
// CExtensionData - the data structure containing all extension data
// CExtDataList - list of extensions defined in the stream
//
// It also contains a function which saves a profile to a file.
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "ExtensionData.h"
#include <stdlib.h>
#include <strsafe.h>
//////////////////////////////////////////////////////////////////////
CExtensionData::CExtensionData( GUID guidDUExt, BYTE *pbExtensionSystemInfo,
WORD cbExtensionDataSize, DWORD cbExtensionSystemInfo, WORD wStreamNum )
: m_guidDUExt( guidDUExt ),
m_cbExtensionDataSize( cbExtensionDataSize ),
m_pbExtensionSystemInfo( pbExtensionSystemInfo ),
m_cbExtensionSystemInfo( cbExtensionSystemInfo ),
m_pNext( NULL ), m_pValue( NULL ), m_wStreamNum( wStreamNum )
{
};
CExtensionData::~CExtensionData()
{
if (NULL != m_pbExtensionSystemInfo)
{
delete [] m_pbExtensionSystemInfo;
m_pbExtensionSystemInfo = NULL;
}
if (NULL != m_pValue)
{
delete [] m_pValue;
m_pValue = NULL;
}
};
//////////////////////////////////////////////////////////////////////
// Display extension data
//////////////////////////////////////////////////////////////////////
HRESULT CExtensionData::DisplayData()
{
HRESULT hr = S_OK;
WCHAR *pwszGuidExtensionType = NULL;
WCHAR *pwszValue = NULL;
WCHAR *pwszSystemInfo = NULL;
WCHAR *pszIter = NULL;
WORD i = 0;
do
{
if( m_cbExtensionSystemInfo > 0 && NULL == m_pbExtensionSystemInfo )
{
hr = E_FAIL;
break;
}
hr = StringFromCLSID( m_guidDUExt, &pwszGuidExtensionType );
if( FAILED( hr ) )
{
break;
}
//
// converts extension data bytes into ASCII
//
pwszValue = new WCHAR[ m_cbExtensionDataSize * 3 + 1 ];
if( NULL == pwszValue )
{
hr = E_OUTOFMEMORY;
break;
}
pszIter = pwszValue;
for( i = 0; i < m_cbExtensionDataSize; i++ )
{
BYTE t = *( ( BYTE * )m_pValue + i );
(void)StringCchPrintfW( pszIter, 4, L" %2.2X", t);
pszIter += 3;
}
*pszIter = L'\0';
//
// Convert extension system info to ASCII
//
pwszSystemInfo = new WCHAR[ m_cbExtensionSystemInfo * 3 + 1 ];
if( NULL == pwszSystemInfo )
{
hr = E_OUTOFMEMORY;
break;
}
pszIter = pwszSystemInfo;
for( i = 0; i < m_cbExtensionSystemInfo; i++ )
{
BYTE t = *( ( BYTE * )m_pbExtensionSystemInfo + i );
(void)StringCchPrintfW( pszIter, 4, L" %2.2X", t);
pszIter += 3;
}
*pszIter = L'\0';
//
// Print the data
//
wprintf( L" ExtGUID : %ws \tExtDataSize : %u \tExtData[0x] : %ws \tExtSystInfoSize : %u \tExtSystInfo[0x] : %ws\n",
pwszGuidExtensionType,
m_cbExtensionDataSize,
pwszValue,
m_cbExtensionSystemInfo,
pwszSystemInfo );
}
while( FALSE );
if( NULL != pwszValue )
{
delete [] pwszValue;
pwszValue = NULL;
}
if( NULL != pwszSystemInfo )
{
delete [] pwszSystemInfo;
pwszSystemInfo = NULL;
}
if ( NULL != pwszGuidExtensionType )
{
CoTaskMemFree( pwszGuidExtensionType );
}
return( hr );
}
//////////////////////////////////////////////////////////////////////
// Create a list of extensions defined in all streams in the profile
//////////////////////////////////////////////////////////////////////
HRESULT CExtDataList::Create( IWMProfile *pProfile )
{
if( NULL == pProfile )
{
return( E_INVALIDARG );
}
DWORD dwStreamCount = 0;
IWMStreamConfig2 *pIWMStreamConfig2 = NULL;
IWMStreamConfig *pIWMStreamConfig = NULL;
HRESULT hr = S_OK;
hr = pProfile->GetStreamCount( &dwStreamCount );
if( FAILED( hr ) )
{
return( E_INVALIDARG );
}
for( DWORD cnt = 0; cnt < dwStreamCount; cnt++ )
{
SAFE_RELEASE( pIWMStreamConfig2 );
SAFE_RELEASE( pIWMStreamConfig );
hr = pProfile->GetStream( cnt , &pIWMStreamConfig );
if( FAILED( hr ) )
{
break;
}
hr = pIWMStreamConfig->QueryInterface( IID_IWMStreamConfig2, (void**)&pIWMStreamConfig2 );
if( FAILED( hr ) )
{
break;
}
CExtensionData *pExtData = NULL;
WORD cDUExts = 0;
hr = pIWMStreamConfig2->GetDataUnitExtensionCount( &cDUExts );
if ( FAILED( hr ) )
{
break;
}
//
//
WORD wStreamNum = 0;
hr = pIWMStreamConfig->GetStreamNumber( &wStreamNum );
if ( FAILED( hr ) )
{
break;
}
for ( WORD i = 0; i < cDUExts; i++ )
{
pExtData = new CExtensionData( GUID_NULL, NULL, 0, 0, wStreamNum );
if( NULL == pExtData )
{
hr = E_OUTOFMEMORY;
break;
}
hr = pIWMStreamConfig2->GetDataUnitExtension( i, &pExtData->m_guidDUExt,
&pExtData->m_cbExtensionDataSize, NULL, &pExtData->m_cbExtensionSystemInfo );
if ( FAILED( hr ) )
{
break;
}
pExtData->m_pbExtensionSystemInfo = new BYTE[ pExtData->m_cbExtensionSystemInfo ];
if( NULL == pExtData->m_pbExtensionSystemInfo )
{
hr = E_OUTOFMEMORY;
break;
}
pExtData->m_pValue = new BYTE[ pExtData->m_cbExtensionDataSize ];
if( NULL == pExtData->m_pValue )
{
hr = E_OUTOFMEMORY;
break;
}
hr = pIWMStreamConfig2->GetDataUnitExtension( i, &pExtData->m_guidDUExt,
&pExtData->m_cbExtensionDataSize,
pExtData->m_pbExtensionSystemInfo,
&pExtData->m_cbExtensionSystemInfo );
if ( FAILED( hr ) )
{
break;
}
//
// add extension info to the list
//
Append( pExtData );
}
if( FAILED( hr ) )
{
if (NULL != pExtData)
{
delete pExtData;
pExtData = NULL;
}
}
}
SAFE_RELEASE( pIWMStreamConfig2 );
SAFE_RELEASE( pIWMStreamConfig );
return hr;
}
//////////////////////////////////////////////////////////////////////
// Add extension data to the lists
//////////////////////////////////////////////////////////////////////
bool CExtDataList::Append( CExtensionData *pCExtensionData )
{
if( NULL == pCExtensionData )
{
return FALSE;
}
m_pCur = m_pEnd;
m_pEnd = pCExtensionData;
m_pEnd->m_pNext = NULL;
(m_pCur ? m_pCur->m_pNext : m_pStart ) = m_pEnd;
m_wSize++;
return( TRUE );
}
//////////////////////////////////////////////////////////////////////
// Iterate through extension data for the given stream.
// Usage :
// -first call with wStreamNum containing actual stream number
// retrieves first extension data for that stream
// -next call with wStreamNum = 0 retrieves next extension data for
// previously passed stream number
// Function returns true if there is extension data, otherwise false
//////////////////////////////////////////////////////////////////////
bool CExtDataList::Find( WORD wStreamNum, CExtensionData **pExtensionData )
{
if( NULL == pExtensionData || ( 0 == wStreamNum && 0 == m_wSearchStreamNum ) )
{
return false;
}
if( wStreamNum > 0 )
{
m_wSearchStreamNum = wStreamNum;
m_pIter = GetStart();
}
if( NULL != m_pIter )
{
for( ; NULL != m_pIter; m_pIter = m_pIter->m_pNext )
{
if( m_pIter->m_wStreamNum == m_wSearchStreamNum )
{
*pExtensionData = m_pIter;
m_pIter = m_pIter->m_pNext;
return true;
}
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTIONS USED TO SAVE PROFILE TO FILE
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Helper function - save profile into memory
///////////////////////////////////////////////////////////////////////////////
HRESULT SaveProfileToMemory( IWMProfile *pIWMProfile,
__deref_out_ecount(*pdwLen) WCHAR **ppwszBuffer,
DWORD *pdwLen )
{
HRESULT hr = S_OK;
IWMProfileManager *pIWMProfileMgr = NULL;
do
{
hr = WMCreateProfileManager( &pIWMProfileMgr );
if( FAILED( hr ) )
{
_tprintf( _T( "WMCreateProfileManager failed: (hr=0x%08x)\n" ), hr );
break;
}
hr = pIWMProfileMgr->SaveProfile( pIWMProfile, NULL, pdwLen );
if( FAILED( hr ) )
{
_tprintf( _T( "pIWMProfileMgr::SaveProfile failed: (hr=0x%08x)\n" ), hr );
break;
}
*ppwszBuffer = new WCHAR[ *pdwLen ];
if( NULL == *ppwszBuffer )
{
hr = E_OUTOFMEMORY;
break;
}
hr = pIWMProfileMgr->SaveProfile( pIWMProfile, *ppwszBuffer, pdwLen );
if( FAILED( hr ) )
{
_tprintf( _T( "pIWMProfileMgr::SaveProfile failed: (hr=0x%08x)\n" ), hr );
break;
}
}
while( FALSE );
SAFE_RELEASE( pIWMProfileMgr );
return( hr );
}
///////////////////////////////////////////////////////////////////////////////
// Save profile to file
///////////////////////////////////////////////////////////////////////////////
HRESULT SaveProfileToFile( const TCHAR *pszFileName, IWMProfile *pIWMProfile )
{
if( ( NULL == pszFileName ) ||
( NULL == pIWMProfile ) )
{
return( E_INVALIDARG );
}
HRESULT hr = S_OK;
DWORD dwLength = 0;
WCHAR *pBuffer = NULL;
HANDLE fd = INVALID_HANDLE_VALUE;
DWORD dwBytesToWrite = 0, dwBytesWritten = 0;
do
{
hr = SaveProfileToMemory( pIWMProfile, &pBuffer, &dwLength );
if( FAILED( hr ) )
{
_tprintf( _T( "SaveProfileToMemory failed: (hr=0x%08x)\n" ), hr );
break;
}
fd = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( INVALID_HANDLE_VALUE == fd )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
break;
}
if( FILE_TYPE_DISK != GetFileType( fd ) )
{
hr = NS_E_INVALID_NAME;
break;
}
dwBytesToWrite = dwLength * sizeof( WCHAR );
if( !WriteFile( fd, pBuffer, dwBytesToWrite, &dwBytesWritten, NULL ) )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
break;
}
if( dwBytesToWrite != dwBytesWritten )
{
hr = E_FAIL;
break;
}
}
while( FALSE );
if( NULL != pBuffer )
{
delete [] pBuffer;
pBuffer = NULL;
}
if( INVALID_HANDLE_VALUE != fd )
{
CloseHandle(fd);
fd = INVALID_HANDLE_VALUE;
}
return( hr );
}