453 lines
12 KiB
C++
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 );
|
|
}
|