Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

794 lines
19 KiB

#include "stdafx.h"
#include "device.h"
#include "enumStorage.h"
#include "resource.h"
#include <stdio.h>
#include <mmreg.h>
//#include "findleak.h"
//DECLARE_THIS_FILE;
#define WCS_MIME_TYPE_ALL L"*/*"
#define WMDM_WAVE_FORMAT_ALL (WORD)0xFFFF
#define WAVE_FORMAT_MSAUDIO 0x161
static const _WAVEFORMATEX g_krgWaveFormatsV1[] =
{
// wFormatTag, nChanneels, nSamplesPerSec, nAvgBytesPerSec, nBlockAlign, wBitsPerSample, cbSize
{ WAVE_FORMAT_MPEGLAYER3, 0, 0, 0, 0, 0, 0 },
{ WAVE_FORMAT_MSAUDIO, 2, 44000, 4000, 0, 0, 0 },
{ WAVE_FORMAT_MSAUDIO, 2, 44000, 16000, 0, 0, 0 }
};
//
// These are for CE version 2, in theory, since the player uses the Highest and Lowest
// entries in the table, the CE version 2 table should "outweight" the CE version 1 table
//
static const _WAVEFORMATEX g_krgWaveFormatsV2[] =
{
// wFormatTag, nChanneels, nSamplesPerSec, nAvgBytesPerSec, nBlockAlign, wBitsPerSample, cbSize
{ WAVE_FORMAT_MPEGLAYER3, 0, 0, 0, 0, 0, 0 },
{ WAVE_FORMAT_MSAUDIO, 2, 1000, 0, 0, 0, 0 },
{ WAVE_FORMAT_MSAUDIO, 2, 44000, 0, 0, 0, 0 }
};
static const LPCWSTR g_kszMimeTypes[] =
{
L"audio/mpeg",
L"audio/x-ms-wma",
L"video/x-ms-wmv",
L"video/x-ms-asf"
};
CDevice::CDevice() :
m_pszInitPath(NULL), m_fAllowVideo(FALSE)
{
}
CDevice::~CDevice()
{
delete [] m_pszInitPath;
}
HRESULT CDevice::Init( LPCWSTR pszInitPath )
{
if( NULL == pszInitPath )
{
return( E_INVALIDARG );
}
m_pszInitPath = new WCHAR[ wcslen(pszInitPath) + 1 ];
if( NULL == m_pszInitPath )
{
return( E_OUTOFMEMORY );
}
wcscpy( m_pszInitPath, pszInitPath );
return( S_OK );
}
STDMETHODIMP CDevice::GetName( LPWSTR pwszName, UINT nMaxChars)
{
HKEY hKey = NULL;
HRESULT hr = S_OK;
if( NULL == pwszName || 0 == nMaxChars )
{
return( E_INVALIDARG );
}
memset( pwszName, 0, sizeof(WCHAR)*nMaxChars );
//
// Indicates the base device
//
if( 0 == _wcsicmp(L"\\", m_pszInitPath ) )
{
if( ERROR_SUCCESS == CeRegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Ident", 0, KEY_READ, &hKey ) )
{
DWORD cbData = nMaxChars * sizeof(WCHAR);
if( ERROR_SUCCESS == CeRegQueryValueEx( hKey, L"Name", NULL, NULL, (LPBYTE)pwszName, &cbData) )
{
CeRegCloseKey( hKey );
}
else
{
hr = HRESULT_FROM_WIN32( GetLastError() );
}
}
else
{
hr = HRESULT_FROM_WIN32( GetLastError() );
}
}
else
{
wcsncpy( pwszName, m_pszInitPath, nMaxChars - 1 );
}
return( hr );
}
STDMETHODIMP CDevice::GetManufacturer( LPWSTR pwszName, UINT nMaxChars)
{
return( E_NOTIMPL );
}
STDMETHODIMP CDevice::GetVersion( DWORD *pdwVersion )
{
CEOSVERSIONINFO osv;
HRESULT hr = S_OK;
if( NULL == pdwVersion )
{
return( E_INVALIDARG );
}
osv.dwOSVersionInfoSize = sizeof(osv);
if( !CeGetVersionEx(&osv) )
{
hr = HRESULT_FROM_WIN32( CeGetLastError() );
if( SUCCEEDED( hr ) )
{
hr = CeRapiGetError();
}
}
else
{
*pdwVersion = osv.dwBuildNumber; // The Build Number of CE should suffice!
}
return( hr );
}
STDMETHODIMP CDevice::GetType( DWORD *pdwType )
{
WCHAR szTestSerialPath[MAX_PATH];
HRESULT hrSerial = S_OK;
WMDMID SerialNumber;
if( NULL == pdwType )
{
return( E_INVALIDARG );
}
*pdwType = 0;
memset( &SerialNumber, 0, sizeof(SerialNumber) );
SerialNumber.cbSize = sizeof(SerialNumber);
//
// TODO:Handle the case for WMDM_DEVICE_TYPE_SECURE!
//
if( 0 == _wcsicmp( L"\\", m_pszInitPath ) )
{
hrSerial = CeUtilGetSerialNumber( L"\\", &SerialNumber, NULL, 0 );
}
else
{
memset( szTestSerialPath, 0, sizeof(szTestSerialPath) );
_snwprintf( szTestSerialPath, sizeof(szTestSerialPath)/sizeof(szTestSerialPath[0]) - 1, L"\\%s", m_pszInitPath );
hrSerial = CeUtilGetSerialNumber( szTestSerialPath, &SerialNumber, NULL, 0 );
}
(*pdwType) = ( WMDM_DEVICE_TYPE_STORAGE | WMDM_DEVICE_TYPE_NONSDMI );
if( S_OK == hrSerial )
{
(*pdwType) |= WMDM_DEVICE_TYPE_SDMI;
}
return( S_OK );
}
STDMETHODIMP CDevice::GetSerialNumber( PWMDMID pSerialNumber, BYTE abMac[WMDM_MAC_LENGTH] )
{
HRESULT hr = S_OK;
WCHAR szTestSerialPath[MAX_PATH];
if( 0 == _wcsicmp( L"\\", m_pszInitPath ) )
{
hr = CeUtilGetSerialNumber( m_pszInitPath, pSerialNumber, NULL, 0 );
}
else
{
memset( szTestSerialPath, 0, sizeof(szTestSerialPath) );
_snwprintf( szTestSerialPath, sizeof(szTestSerialPath)/sizeof(szTestSerialPath[0]) - 1, L"\\%s", m_pszInitPath );
hr = CeUtilGetSerialNumber( szTestSerialPath, pSerialNumber, NULL, 0 );
}
if( hr == S_OK )
{
// MAC the parameters
HMAC hMAC;
hr = g_pAppSCServer->MACInit(&hMAC);
if( SUCCEEDED( hr ) )
{
hr = g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pSerialNumber), sizeof(WMDMID));
}
if( SUCCEEDED( hr ) )
{
hr = g_pAppSCServer->MACFinal(hMAC, abMac);
}
}
else
{
hr = WMDM_E_NOTSUPPORTED;
}
return( hr );
}
STDMETHODIMP CDevice::GetPowerSource( DWORD *pdwPowerSource, DWORD *pdwPercentRemaining)
{
SYSTEM_POWER_STATUS_EX sps;
HRESULT hr = S_OK;
if( NULL == pdwPowerSource )
{
return( E_POINTER );
}
*pdwPowerSource = 0;
if( pdwPercentRemaining )
{
*pdwPercentRemaining = 0;
}
if( !CeGetSystemPowerStatusEx( &sps, TRUE) )
{
hr = HRESULT_FROM_WIN32( CeGetLastError() );
if( SUCCEEDED( hr ) )
{
hr = CeRapiGetError();
}
}
if( SUCCEEDED( hr ) )
{
if( 1 == sps.ACLineStatus )
{
*pdwPowerSource |= WMDM_POWER_IS_EXTERNAL;
}
else if( 0 == sps.ACLineStatus )
{
*pdwPowerSource |= WMDM_POWER_IS_BATTERY;
}
if( 255 != sps.ACLineStatus )
{
*pdwPowerSource |= WMDM_POWER_CAP_EXTERNAL;
}
if( 128 != sps.BatteryFlag && 255 != sps.BatteryFlag )
{
*pdwPowerSource |= WMDM_POWER_CAP_BATTERY;
}
if( pdwPercentRemaining )
{
if( 255 != sps.BatteryLifePercent )
{
*pdwPercentRemaining = sps.BatteryLifePercent;
}
}
}
return( hr );
}
STDMETHODIMP CDevice::GetStatus( DWORD *pdwStatus )
{
if( NULL == pdwStatus )
{
return( E_INVALIDARG );
}
//
// We may want to extend this in the future to handle
// the player is playing, currently copying to device, etc!
//
if( !_Module.g_fDeviceConnected )
{
*pdwStatus = WMDM_STATUS_DEVICE_NOTPRESENT;
}
else
{
*pdwStatus = WMDM_STATUS_READY;
}
return( S_OK );
}
STDMETHODIMP CDevice::GetDeviceIcon( ULONG *hIcon )
{
HRESULT hr = S_OK;
if( NULL == hIcon )
{
return( E_POINTER );
}
*hIcon = HandleToULong(LoadIcon(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_CEWMDM_DEVICE) ));
if( NULL == *hIcon )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
}
return( hr );
}
STDMETHODIMP CDevice::EnumStorage( IMDSPEnumStorage **ppEnumStorage )
{
HRESULT hr = S_OK;
CComEnumStorage *pEnumStorage = NULL;
CComPtr<IMDSPEnumStorage> spEnum;
if( NULL == ppEnumStorage )
{
return( E_INVALIDARG );
}
*ppEnumStorage = NULL;
hr = CComEnumStorage::CreateInstance( &pEnumStorage );
spEnum = pEnumStorage;
if( SUCCEEDED( hr ) )
{
hr = pEnumStorage->Init( m_pszInitPath, TRUE, this );
}
if( SUCCEEDED( hr ) )
{
*ppEnumStorage = spEnum;
spEnum.Detach();
}
return( hr );
}
STDMETHODIMP CDevice::GetFormatSupport( _WAVEFORMATEX **pFormatEx,
UINT *pnFormatCount,
LPWSTR **pppwszMimeType,
UINT *pnMimeTypeCount)
{
return InternalGetFormatSupport( pFormatEx, pnFormatCount, pppwszMimeType, pnMimeTypeCount );
}
STDMETHODIMP CDevice::SendOpaqueCommand( OPAQUECOMMAND *pCommand )
{
return( E_NOTIMPL );
}
STDMETHODIMP CDevice::GetStorage( LPCWSTR pszStorageName, IMDSPStorage** ppStorage )
{
return ( E_NOTIMPL );
}
STDMETHODIMP CDevice::GetPnPName( LPWSTR pwszPnPName, UINT nMaxChars )
{
return E_NOTIMPL;
}
STDMETHODIMP CDevice::GetFormatSupport2( DWORD dwFlags,
_WAVEFORMATEX **ppAudioFormatEx,
UINT *pnAudioFormatCount,
_VIDEOINFOHEADER **ppVideoFormatEx,
UINT *pnVideoFormatCount,
WMFILECAPABILITIES **ppFileType,
UINT *pnFileTypeCount)
{
HRESULT hr = S_OK;
LPWSTR *ppwszMimeType = NULL;
UINT nMimeTypeCount;
BOOL fAllowVideo = FALSE;
if( NULL != pnVideoFormatCount )
{
*pnVideoFormatCount = 0;
}
if( NULL != ppVideoFormatEx )
{
*ppVideoFormatEx = NULL;
}
if( NULL != pnFileTypeCount )
{
*pnFileTypeCount = 0;
}
if( NULL != ppFileType )
{
*ppFileType = NULL;
}
if( NULL == pnVideoFormatCount )
{
return( E_INVALIDARG );
}
if( NULL == ppVideoFormatEx )
{
return( E_INVALIDARG );
}
if( NULL == pnFileTypeCount )
{
return( E_INVALIDARG );
}
if( NULL == ppFileType )
{
return( E_INVALIDARG );
}
if ( SUCCEEDED(hr) )
{
// NOTE: This function calls GetCEPlayerVersion which sets m_fAllowVideo
// if you need to put code above this call that depends on that member you must call GetCEPlayerVersion first
hr = InternalGetFormatSupport( ppAudioFormatEx, pnAudioFormatCount, &ppwszMimeType, &nMimeTypeCount );
if ( SUCCEEDED(hr) )
{
// Wrap all of the mime types in WMFILECAPABILITIES
*ppFileType = (WMFILECAPABILITIES *)CoTaskMemAlloc( sizeof(WMFILECAPABILITIES) * nMimeTypeCount );
if (*ppFileType)
{
memset( *ppFileType, 0, sizeof(WMFILECAPABILITIES) * nMimeTypeCount );
for (UINT x=0; x < nMimeTypeCount; x++)
{
(*ppFileType)[x].pwszMimeType = ppwszMimeType[x];
}
*pnFileTypeCount = nMimeTypeCount;
}
else
{
// If the memory alloc fail we need to clean up the return values from GetFormatSupport and the video format struct
hr = E_OUTOFMEMORY;
}
}
}
// If it is the V2 regkey, tell the WMDM that we can support video
if ( SUCCEEDED(hr) && m_fAllowVideo )
{
*ppVideoFormatEx = (_VIDEOINFOHEADER *)CoTaskMemAlloc( sizeof(_VIDEOINFOHEADER) );
if (*ppVideoFormatEx)
{
memset( *ppVideoFormatEx, 0, sizeof(_VIDEOINFOHEADER) );
// Setup the WMDMVIDEOINFOHEADER structure for video
// These values are all being ignored by WMP8
(*ppVideoFormatEx)->bmiHeader.biSize = sizeof(_BITMAPINFOHEADER);
*pnVideoFormatCount = 1;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if ( FAILED(hr) )
{
if ( ppAudioFormatEx )
{
if ( *ppAudioFormatEx )
{
CoTaskMemFree(*ppAudioFormatEx);
}
}
if ( ppwszMimeType )
{
if ( *ppwszMimeType )
{
while( nMimeTypeCount-- )
{
CoTaskMemFree( ppwszMimeType[nMimeTypeCount] );
}
}
CoTaskMemFree(ppwszMimeType);
}
}
return ( hr );
}
STDMETHODIMP CDevice::GetSpecifyPropertyPages( ISpecifyPropertyPages** ppSpecifyPropPages,
IUnknown*** pppUnknowns,
ULONG *pcUnks )
{
HRESULT hr = S_OK;
HINSTANCE hInstance = NULL;
DWORD dwVersion = 1;
hInstance = LoadLibrary( _T("wmploc.dll") );
if( NULL == hInstance )
{
return( E_NOTIMPL );
}
FreeLibrary( hInstance );
GetCEPlayerVersion( &dwVersion );
if( dwVersion < 3 )
{
return( E_NOTIMPL );
}
if( NULL == ppSpecifyPropPages )
{
hr = E_POINTER;
}
else
{
*ppSpecifyPropPages = NULL;
}
if( NULL != pppUnknowns )
{
*pppUnknowns = NULL;
}
if( NULL != pcUnks )
{
*pcUnks = 0;
}
if( SUCCEEDED( hr ) )
{
hr = QueryInterface( __uuidof(ISpecifyPropertyPages), (LPVOID *)ppSpecifyPropPages );
}
return ( hr );
}
STDMETHODIMP CDevice::GetCEPlayerVersion(DWORD *pdwVersion)
{
HRESULT hr = S_OK;
HKEY hkeyVer = NULL;
if (NULL == pdwVersion)
{
return (E_INVALIDARG);
}
else
{
*pdwVersion = 1;
}
// Check the NOW continuously updated reg key on the device (this should NEVER MOVE on the CE player)
if( ERROR_SUCCESS != CeRegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\wmdm\\CurrentInUseVersion", 0, KEY_READ, &hkeyVer ) )
{
//
// On RAPIER Casio Devices, this call fails if the reg key isn't there, but RETURNS a handle, ugly....
//
hkeyVer = NULL;
}
// Check the regkey on the CE device
WCHAR szTargetApp[MAX_PATH];
if ( NULL == hkeyVer )
{
if( ERROR_SUCCESS != CeRegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows Media Player 2\\Version", 0, KEY_READ, &hkeyVer ) )
{
//
// On RAPIER Casio Devices, this call fails if the reg key isn't there, but RETURNS a handle, ugly....
//
hkeyVer = NULL;
}
}
if( NULL != hkeyVer )
{
DWORD cbData = sizeof(szTargetApp);
if( ERROR_SUCCESS == CeRegQueryValueEx( hkeyVer, NULL, NULL, NULL, (LPBYTE)szTargetApp, &cbData ) )
{
LPWSTR pszSplit = wcsrchr( szTargetApp, L'.' );
DWORD hi, lo;
if( NULL != pszSplit )
{
*pszSplit = L'\0';
pszSplit++;
hi = _wtoi( szTargetApp );
lo = _wtoi( pszSplit );
if( hi >= 2 )
{
m_fAllowVideo = TRUE;
}
*pdwVersion = hi;
hr = S_OK;
}
}
CeRegCloseKey( hkeyVer );
}
return hr;
}
STDMETHODIMP CDevice::InternalGetFormatSupport( _WAVEFORMATEX **pFormatEx,
UINT *pnFormatCount,
LPWSTR **pppwszMimeType,
UINT *pnMimeTypeCount)
{
HRESULT hr = S_OK;
UINT idxMimes = 0;
UINT cMimes = 0;
UINT cWaves = 0;
const _WAVEFORMATEX *prgWaveFormats = NULL;
if( NULL != pnFormatCount )
{
*pnFormatCount = 0;
}
if( NULL != pFormatEx )
{
*pFormatEx = NULL;
}
if( NULL != pppwszMimeType )
{
*pppwszMimeType = NULL;
}
if( NULL != pnMimeTypeCount )
{
*pnMimeTypeCount = 0;
}
if( NULL == pnFormatCount )
{
return( E_INVALIDARG );
}
if( NULL == pFormatEx )
{
return( E_INVALIDARG );
}
if( NULL == pppwszMimeType )
{
return( E_INVALIDARG );
}
if( NULL == pnMimeTypeCount )
{
return( E_INVALIDARG );
}
DWORD dwVersion;
hr = GetCEPlayerVersion(&dwVersion);
if(SUCCEEDED( hr ))
{
if( m_fAllowVideo )
{
cWaves = sizeof(g_krgWaveFormatsV2)/sizeof(g_krgWaveFormatsV2[0]);
prgWaveFormats = g_krgWaveFormatsV2;
}
else
{
cWaves = sizeof(g_krgWaveFormatsV1)/sizeof(g_krgWaveFormatsV1[0]);
prgWaveFormats = g_krgWaveFormatsV1;
}
}
if (SUCCEEDED(hr))
{
*pFormatEx = (_WAVEFORMATEX *)CoTaskMemAlloc(sizeof(_WAVEFORMATEX) * cWaves );
if( NULL == *pFormatEx )
{
hr = E_OUTOFMEMORY;
}
}
if( SUCCEEDED( hr ) )
{
*pnFormatCount = cWaves;
memcpy( *pFormatEx, prgWaveFormats, sizeof(_WAVEFORMATEX) * cWaves );
}
if( SUCCEEDED( hr ) )
{
cMimes = (sizeof(g_kszMimeTypes) / sizeof(g_kszMimeTypes[0]) - (m_fAllowVideo ? 0 : 2));
*pppwszMimeType = (LPWSTR *)CoTaskMemAlloc( sizeof(LPWSTR) * cMimes );
if( NULL == pppwszMimeType )
{
hr = E_OUTOFMEMORY;
}
else
{
for( idxMimes = 0; idxMimes < cMimes; idxMimes++ )
{
(*pppwszMimeType)[idxMimes] = NULL;
}
}
}
if( SUCCEEDED( hr ) )
{
for( idxMimes = 0; SUCCEEDED( hr ) && idxMimes < cMimes; idxMimes++ )
{
(*pppwszMimeType)[idxMimes] = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(g_kszMimeTypes[idxMimes])+1));
if( NULL == (*pppwszMimeType)[idxMimes] )
{
hr = E_OUTOFMEMORY;
}
else
{
wcscpy( (*pppwszMimeType)[idxMimes], g_kszMimeTypes[idxMimes]);
}
}
}
if( SUCCEEDED( hr ) )
{
*pnMimeTypeCount = cMimes;
}
else
{
if( *pppwszMimeType )
{
for( idxMimes = 0; SUCCEEDED( hr ) && idxMimes < cMimes; idxMimes++ )
{
if( NULL != (*pppwszMimeType)[idxMimes] )
{
CoTaskMemFree( (*pppwszMimeType)[idxMimes] );
}
}
CoTaskMemFree( *pppwszMimeType );
*pppwszMimeType = NULL;
}
if( *pFormatEx )
{
CoTaskMemFree( *pFormatEx );
*pFormatEx = NULL;
}
*pnMimeTypeCount = 0;
*pnFormatCount = 0;
}
return( hr );
}