628 lines
22 KiB
C++
628 lines
22 KiB
C++
//*****************************************************************************
|
|
//
|
|
// Microsoft Windows Media
|
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// FileName: DRMReader.cpp
|
|
//
|
|
// Abstract: This file contains the implementation for the
|
|
// CLicenseViewer class, which can show the DRM-related
|
|
// properties of the file, including information about any
|
|
// licenses the user may have for the content.
|
|
//
|
|
// For examples about how to query the DRM reader for
|
|
// properties, see the ShowRights method
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "stdafx.h"
|
|
#include "DRMReader.h"
|
|
#include "assert.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
typedef struct tag_DRM_Properties
|
|
{
|
|
const WCHAR* pwszName; // Name of the DRM property to test
|
|
WMT_ATTR_DATATYPE wmtExpectedType; // Its expected type - we'll break on mismatch
|
|
WORD cbExpectedLength; // Its expected length - we'll break on mismatch
|
|
}
|
|
DRM_Properties;
|
|
|
|
static const DRM_Properties g_BoolProperties[] =
|
|
{
|
|
{ g_wszWMDRM_IsDRM, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if the file is DRM-protected
|
|
{ g_wszWMDRM_IsDRMCached, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if license was created locally
|
|
{ g_wszWMDRM_ActionAllowed_Playback, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if license allows playback
|
|
{ g_wszWMDRM_ActionAllowed_CopyToCD, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if license allows writing to a CD
|
|
{ g_wszWMDRM_ActionAllowed_CopyToNonSDMIDevice, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if license allows tranfer to a non-SDMI compliant device
|
|
{ g_wszWMDRM_ActionAllowed_CopyToSDMIDevice, WMT_TYPE_BOOL, sizeof( BOOL ) }, // True if license allows tranfer to a SDMI compliant device
|
|
{ g_wszWMDRM_ActionAllowed_Backup, WMT_TYPE_BOOL, sizeof( BOOL ) } // True if license allows itself to be backed-up
|
|
};
|
|
|
|
#define NUM_BOOL_PROPERTIES ( sizeof( g_BoolProperties ) / sizeof(g_BoolProperties[ 0 ] ) )
|
|
|
|
static const DRM_Properties g_LicenseProperties[] =
|
|
{
|
|
{ g_wszWMDRM_LicenseState_Playback, WMT_TYPE_BINARY, sizeof( WM_LICENSE_STATE_DATA ) }, // License data related to playback
|
|
{ g_wszWMDRM_LicenseState_CopyToCD, WMT_TYPE_BINARY, sizeof( WM_LICENSE_STATE_DATA ) }, // License data related to writing content to CD
|
|
{ g_wszWMDRM_LicenseState_CopyToNonSDMIDevice, WMT_TYPE_BINARY, sizeof( WM_LICENSE_STATE_DATA ) }, // License data related to transfer to non-SDMI compliant devices
|
|
{ g_wszWMDRM_LicenseState_CopyToSDMIDevice, WMT_TYPE_BINARY, sizeof( WM_LICENSE_STATE_DATA ) } // License data related to transfer to SDMI compliant devices
|
|
};
|
|
|
|
#define NUM_LICENSE_PROPERTIES ( sizeof( g_LicenseProperties ) / sizeof( g_LicenseProperties[ 0 ] ) )
|
|
|
|
static const DRM_Properties g_HeaderProperties[] =
|
|
{
|
|
{ L"DRMHeader.KID", WMT_TYPE_STRING, 0 }, // The Key ID for the content
|
|
{ L"DRMHeader.LAINFO", WMT_TYPE_STRING, 0 } // The license acquisition URL for the content
|
|
};
|
|
|
|
#define NUM_HEADER_PROPERTIES ( sizeof( g_HeaderProperties ) / sizeof( g_HeaderProperties[ 0 ] ) )
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::CLicenseViewer()
|
|
// Desc: Constructor.
|
|
//------------------------------------------------------------------------------
|
|
CLicenseViewer::CLicenseViewer()
|
|
{
|
|
m_pIWMReader = NULL;
|
|
m_pIWMDRMReader = NULL;
|
|
m_hEvent = NULL;
|
|
m_cRef = 1;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::~CLicenseViewer()
|
|
// Desc: Destructor.
|
|
//------------------------------------------------------------------------------
|
|
CLicenseViewer::~CLicenseViewer()
|
|
{
|
|
Cleanup();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::Initialize()
|
|
// Desc: Initialization.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CLicenseViewer::Initialize()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Reset the m_hr variable
|
|
//
|
|
m_hr = S_OK;
|
|
|
|
//
|
|
// Create callback event, if it doesn't already exist
|
|
//
|
|
if ( NULL == m_hEvent )
|
|
{
|
|
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
if ( !m_hEvent )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ::GetLastError() );
|
|
_tprintf( _T( "CreateEvent failed 0x%08lX\n" ), hr );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a Reader and get the DRM reader interface
|
|
//
|
|
if ( NULL == m_pIWMReader )
|
|
{
|
|
hr = WMCreateReader( NULL, 0, &m_pIWMReader );
|
|
if ( FAILED( hr ) || NULL == m_pIWMReader )
|
|
{
|
|
hr = E_FAIL;
|
|
_tprintf( _T( "Failed to create WMReader 0x%08lX\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
SAFE_RELEASE( m_pIWMDRMReader );
|
|
assert( m_pIWMReader );
|
|
hr = m_pIWMReader->QueryInterface( IID_IWMDRMReader, ( void **)&m_pIWMDRMReader );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Failed to QI for DRM Reader interface 0x%08lX\n" ), hr );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while ( FALSE );
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::OnSample()
|
|
// Desc: Implementation of IWMReaderCallback::OnSample.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CLicenseViewer::OnSample( DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer __RPC_FAR *pSample, void *pvContext )
|
|
{
|
|
//
|
|
// No samples are expected, but a value must be returned
|
|
//
|
|
return( S_OK );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::OnStatus()
|
|
// Desc: Implementation of IWMStatusCallback::OnStatus.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CLicenseViewer::OnStatus( WMT_STATUS Status, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext )
|
|
{
|
|
//
|
|
// If the file has been opened (even if there was an error), then set the event so that
|
|
// the other thread can stop waiting, since OnStatus is called on the WMFSDK's thread
|
|
//
|
|
switch ( Status )
|
|
{
|
|
case WMT_OPENED:
|
|
_tprintf( _T( "WMT_OPENED 0x%08lX\n" ), hr );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
m_hr = hr; // Set the m_hr member variable so the error can be addressed later
|
|
}
|
|
assert( m_hEvent );
|
|
SetEvent( m_hEvent );
|
|
break;
|
|
}
|
|
|
|
return( S_OK );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Implementation of IUnknown methods
|
|
//------------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CLicenseViewer::QueryInterface( REFIID riid, void **ppvObject )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( riid == IID_IWMReaderCallback )
|
|
{
|
|
AddRef();
|
|
*ppvObject = ( IWMReaderCallback* )this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObject = NULL;
|
|
return( E_NOINTERFACE );
|
|
}
|
|
|
|
return( hr );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
ULONG STDMETHODCALLTYPE CLicenseViewer::AddRef( void )
|
|
{
|
|
return( InterlockedIncrement( &m_cRef ) );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
ULONG STDMETHODCALLTYPE CLicenseViewer::Release( void )
|
|
{
|
|
if ( 0 == InterlockedDecrement( &m_cRef ) )
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return( m_cRef );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::Close()
|
|
// Desc: Close the reader.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CLicenseViewer::Close( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( NULL != m_pIWMReader )
|
|
{
|
|
hr = m_pIWMReader->Close();
|
|
}
|
|
|
|
return ( hr );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::Open()
|
|
// Desc: Create and open the reader.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CLicenseViewer::Open( __in LPWSTR pwszInFile )
|
|
{
|
|
static const DWORD OPEN_WAIT_LENGTH = 30000;
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Create the reader and callback event, if not already done
|
|
//
|
|
hr = Initialize();
|
|
if ( FAILED( hr ) )
|
|
break;
|
|
|
|
//
|
|
// Validate input parameter
|
|
//
|
|
if ( NULL == pwszInFile )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
_tprintf( _T( "Filename should not be NULL.\n" ) );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Open the input file
|
|
//
|
|
assert( m_pIWMReader );
|
|
hr = m_pIWMReader->Open( pwszInFile, this, NULL );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( "Failed to open file 0x%08lX\n" ), hr );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Wait for the WMT_OPENED message to be sent, signaling the file has been opened. This
|
|
// message is received in the OnStatus method
|
|
//
|
|
assert( m_hEvent );
|
|
if ( WAIT_TIMEOUT == WaitForSingleObject( m_hEvent, OPEN_WAIT_LENGTH ) )
|
|
{
|
|
_tprintf( _T( "Failed to open file in a reasonable amount of time.\n" ) );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check the m_hr variable, which will get set if an error occured while opening the file.
|
|
// m_hr will get set in the OnStatus method.
|
|
//
|
|
if ( FAILED( m_hr ) )
|
|
{
|
|
hr = m_hr;
|
|
|
|
switch( m_hr )
|
|
{
|
|
case NS_E_LICENSE_REQUIRED:
|
|
_tprintf( _T( "A license is required to open the given file.\n" ) );
|
|
break;
|
|
|
|
default:
|
|
_tprintf( _T( "An error occured while opening file \"%ws\": %0.8x.\n" ), pwszInFile, hr );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
while( FALSE );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
Cleanup();
|
|
}
|
|
|
|
return( hr );
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::PrintLicenseStateData()
|
|
// Desc: Display license data.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CLicenseViewer::PrintLicenseStateData( LPCTSTR tszOutputPrefix, DRM_LICENSE_STATE_DATA* pDRMLicenseStateData )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCountIndex;
|
|
DWORD dwDateIndex;
|
|
|
|
assert( tszOutputPrefix );
|
|
assert( pDRMLicenseStateData );
|
|
|
|
do
|
|
{
|
|
//
|
|
// Print the type of right given by aggregating all the licenses for the content
|
|
//
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwStreamId: %ld\n" ), tszOutputPrefix, pDRMLicenseStateData->dwStreamId );
|
|
switch( pDRMLicenseStateData->dwCategory )
|
|
{
|
|
case WM_DRM_LICENSE_STATE_NORIGHT: // No rights to perform this action
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_NORIGHT\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_UNLIM: // Unlimited rights to perform this action
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_UNLIM\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_COUNT: // Action may only be performed a certain number of times
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_COUNT\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_FROM: // Action cannot be performed until a specific date
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_FROM\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_UNTIL: // Action cannot be performed after a certain date
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_UNTIL\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_FROM_UNTIL: // Action can only be performed within a specific range of dates
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_FROM_UNTIL\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_COUNT_FROM: // Action can only be performed a certain number of times, starting from a specific date
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_COUNT_FROM\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_COUNT_UNTIL: // Action can be performed a certain number of times until a specific date
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_COUNT_UNTIL\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_COUNT_FROM_UNTIL: // Action can only be performed a certain number of times, and only is a specific range of dates
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_COUNT_FROM_UNTIL\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
case WM_DRM_LICENSE_STATE_EXPIRATION_AFTER_FIRSTUSE: // License restrictions don't occur until after the first use
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: WM_DRM_LICENSE_STATE_EXPIRATION_AFTER_FIRSTUSE\n" ), tszOutputPrefix );
|
|
break;
|
|
|
|
default:
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCategory: Unknown! - %d\n" ), tszOutputPrefix, pDRMLicenseStateData->dwCategory );
|
|
}
|
|
|
|
//
|
|
// If count limited, print the number of times the action can be performed
|
|
//
|
|
if ( 0 != pDRMLicenseStateData->dwNumCounts )
|
|
{
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwCount:" ), tszOutputPrefix );
|
|
for( dwCountIndex = 0; dwCountIndex < pDRMLicenseStateData->dwNumCounts; dwCountIndex++ )
|
|
{
|
|
_tprintf( _T( " %ld" ), pDRMLicenseStateData->dwCount[ dwCountIndex ] );
|
|
}
|
|
_tprintf( _T( "\n" ) );
|
|
}
|
|
|
|
//
|
|
// If the action is date limited, print the date restriction(s)
|
|
//
|
|
if ( 0 != pDRMLicenseStateData->dwNumDates )
|
|
{
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.datetime:" ), tszOutputPrefix );
|
|
for( dwDateIndex = 0; dwDateIndex < pDRMLicenseStateData->dwNumDates; dwDateIndex++ )
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
WCHAR wszOn[128];
|
|
WCHAR wszAt[128];
|
|
|
|
//
|
|
// Convert the FILETIME to SYSTEMTIME and format into strings
|
|
//
|
|
FileTimeToSystemTime( &(pDRMLicenseStateData->datetime[ dwDateIndex ]), &SystemTime );
|
|
GetDateFormatW( LOCALE_USER_DEFAULT, 0, &SystemTime, L"ddd',' MMM dd yyyy", wszOn, 128 );
|
|
GetTimeFormatW( LOCALE_USER_DEFAULT, 0, &SystemTime, L"hh mm ss tt", wszAt, 128 );
|
|
|
|
_tprintf( _T( " On %ws at %ws" ), wszOn, wszAt );
|
|
}
|
|
_tprintf( _T( "\n" ) );
|
|
}
|
|
|
|
//
|
|
// If the aggregate license data cannot easily be represented, the "vague" value will be set.
|
|
// This will happen when two or more licenses with different right types (like COUNT and
|
|
// and FROM_UNTIL) make it impossible to represent the information simply. For instance,
|
|
// if license 1 allows 5 plays and license 2 allows unlimited playback during the current
|
|
// month, then the user is guaranteed at least 5 plays, but possibly an unlimited number,
|
|
// if done within the current month.
|
|
//
|
|
_tprintf( _T( "%sDRM_LICENSE_DATA.dwVague: %ld \n" ), tszOutputPrefix, pDRMLicenseStateData->dwVague );
|
|
}
|
|
while ( FALSE );
|
|
|
|
return hr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::ShowRights()
|
|
// Desc: Show DRM rights properties.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CLicenseViewer::ShowRights()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwPropertyIndex;
|
|
WMT_ATTR_DATATYPE wmtType;
|
|
BOOL fBoolProperty;
|
|
WORD cbLength;
|
|
WM_LICENSE_STATE_DATA LicenseStateData;
|
|
WCHAR wszTemp[500];
|
|
LPCWSTR wszPropertyName;
|
|
const DRM_Properties* pCurrentProperty;
|
|
LPBYTE pbProperty = NULL;
|
|
DWORD dwStateIndex;
|
|
|
|
//
|
|
// Validate current state
|
|
//
|
|
if ( !m_pIWMDRMReader )
|
|
{
|
|
_tprintf( _T( "ShowRights: m_pIWMDRMReader is NULL." ) );
|
|
return E_FAIL;
|
|
}
|
|
|
|
_tprintf( _T( "ShowRights 0x%08lX\n" ), hr );
|
|
|
|
//
|
|
// Print the boolean properties
|
|
//
|
|
_tprintf( _T( " Basic rights information:\n" ) );
|
|
|
|
for ( dwPropertyIndex = 0; dwPropertyIndex < NUM_BOOL_PROPERTIES; dwPropertyIndex++ )
|
|
{
|
|
pCurrentProperty = &(g_BoolProperties[ dwPropertyIndex ]);
|
|
|
|
//
|
|
// Get the next property from the DRM reader
|
|
//
|
|
wszPropertyName = pCurrentProperty->pwszName;
|
|
cbLength = sizeof( BOOL );
|
|
assert( m_pIWMDRMReader );
|
|
assert( pCurrentProperty );
|
|
hr = m_pIWMDRMReader->GetDRMProperty( wszPropertyName, &wmtType, (BYTE *)&fBoolProperty, &cbLength );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( " Couldn't get value for property %ws (hr = 0x%08lX)\n" ), wszPropertyName, hr );
|
|
hr = S_OK; // Reset the HRESULT, since it was "handled"
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check to make sure the property is the expected type and size
|
|
//
|
|
if ( wmtType != pCurrentProperty->wmtExpectedType )
|
|
{
|
|
_tprintf( _T( " Invalid returned property type\n" ) );
|
|
continue;
|
|
}
|
|
|
|
if ( sizeof( BOOL ) != cbLength )
|
|
{
|
|
_tprintf( _T( " Invalid returned property length\n" ) );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Print the value of the property
|
|
//
|
|
_tprintf( _T( " %ws: %Ls\n" ), wszPropertyName, fBoolProperty ? _T( "Yes" ) : _T( "No" ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the license state properties
|
|
//
|
|
_tprintf( _T( " Content rights information:\n" ) );
|
|
|
|
for( dwPropertyIndex = 0; dwPropertyIndex < NUM_LICENSE_PROPERTIES; dwPropertyIndex++ )
|
|
{
|
|
pCurrentProperty = &(g_LicenseProperties[ dwPropertyIndex ]);
|
|
|
|
//
|
|
// Get property from DRM reader
|
|
//
|
|
cbLength = pCurrentProperty->cbExpectedLength;
|
|
assert( m_pIWMDRMReader );
|
|
assert( pCurrentProperty );
|
|
hr = m_pIWMDRMReader->GetDRMProperty( pCurrentProperty->pwszName, &wmtType, (BYTE *)&LicenseStateData, &cbLength );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( " Couldn't get value for property %ws (hr = 0x%08lX)\n" ), pCurrentProperty->pwszName, hr );
|
|
hr = S_OK; // Reset the HRESULT, since it was "handled"
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check that the property type and size are the expected values
|
|
//
|
|
if ( wmtType != pCurrentProperty->wmtExpectedType )
|
|
{
|
|
_tprintf( _T( " Invalid returned property type\n" ) );
|
|
continue;
|
|
}
|
|
|
|
if ( cbLength != pCurrentProperty->cbExpectedLength )
|
|
{
|
|
_tprintf( _T( " Invalid returned property length\n" ) );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Print each license state
|
|
//
|
|
_tprintf( _T( " %ws:\n" ), pCurrentProperty->pwszName );
|
|
for( dwStateIndex = 0; dwStateIndex < LicenseStateData.dwNumStates; dwStateIndex++ )
|
|
{
|
|
hr = PrintLicenseStateData( _T(" "), &(LicenseStateData.stateData[ dwStateIndex ]) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( FAILED( hr ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Test the Header properties
|
|
//
|
|
_tprintf( _T( " Header Properies:\n" ) );
|
|
|
|
for( dwPropertyIndex = 0; dwPropertyIndex < NUM_HEADER_PROPERTIES; dwPropertyIndex++ )
|
|
{
|
|
pCurrentProperty = &(g_HeaderProperties[ dwPropertyIndex ]);
|
|
|
|
//
|
|
// Get the property from the DRM reader
|
|
//
|
|
cbLength = sizeof( wszTemp );
|
|
assert( m_pIWMDRMReader );
|
|
assert( pCurrentProperty );
|
|
hr = m_pIWMDRMReader->GetDRMProperty( pCurrentProperty->pwszName, &wmtType, (BYTE *)&wszTemp[ 0 ], &cbLength );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
_tprintf( _T( " Couldn't get value for property %ws (hr = 0x%08lX)\n" ), pCurrentProperty->pwszName, hr );
|
|
hr = S_OK; // Reset the HRESULT, since it was "handled"
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check that the type returned is the expected type
|
|
//
|
|
if ( wmtType != pCurrentProperty->wmtExpectedType )
|
|
{
|
|
_tprintf( _T( " Invalid returned property type\n" ) );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Print the value of the property
|
|
//
|
|
_tprintf( _T( " %ws: %ws\n" ), pCurrentProperty->pwszName, wszTemp );
|
|
}
|
|
}
|
|
|
|
SAFE_ARRAYDELETE( pbProperty );
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Name: CLicenseViewer::Cleanup()
|
|
// Desc: Release resources.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CLicenseViewer::Cleanup()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Release all resources held in member variables
|
|
//
|
|
SAFE_RELEASE( m_pIWMDRMReader );
|
|
SAFE_RELEASE( m_pIWMReader );
|
|
SAFE_CLOSEHANDLE( m_hEvent );
|
|
|
|
return( hr );
|
|
}
|
|
|