// Device.cpp : Implementation of CDevice #include "stdafx.h" #include "mswmdm.h" #include "Device.h" #include "Storage.h" #include "WMDMStorageEnum.h" #include "loghelp.h" #include "scserver.h" #include "scclient.h" #include "spinfo.h" #define DISABLE_DRM_LOG #include ///////////////////////////////////////////////////////////////////////////// // CWMDMDevice extern CSecureChannelServer *g_pAppSCServer; extern CSPInfo **g_pSPs; CWMDMDevice::CWMDMDevice() : m_pDevice(NULL) { GlobalAddRef(); } CWMDMDevice::~CWMDMDevice() { if (m_pDevice) m_pDevice->Release(); GlobalRelease(); } //IWMDMDevice Methods HRESULT CWMDMDevice::GetName(LPWSTR pwszName, UINT nMaxChars) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetName(pwszName, nMaxChars) ); Error: hrLogDWORD("IWMDMDevice::GetName returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetManufacturer(LPWSTR pwszName, UINT nMaxChars) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetManufacturer(pwszName, nMaxChars) ); Error: hrLogDWORD("IWMDMDevice::GetManufacturer returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetVersion(DWORD *pdwVersion) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetVersion(pdwVersion) ); Error: hrLogDWORD("IWMDMDevice::GetVersion returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetType(DWORD *pdwType) { HRESULT hr; CARg (pdwType); if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetType(pdwType) ); #if 0 ////////////////////////////////////////// //RC1 Hack for non-reentrant devices ////////////////////////////////////////// WCHAR wszManufacturer[MAX_PATH]; CORg(m_pDevice->GetManufacturer (wszManufacturer, MAX_PATH)); if (wcsstr(_wcsupr(wszManufacturer), L"S3/DIAMOND MULTIMEDIA")) { *pdwType |= WMDM_DEVICE_TYPE_NONREENTRANT | WMDM_DEVICE_TYPE_FILELISTRESYNC; } #endif ////////////////////////////////////////// Error: hrLogDWORD("IWMDMDevice::GetType returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetSerialNumber(PWMDMID pSerialNumber, BYTE abMac[WMDM_MAC_LENGTH]) { HRESULT hr; HMAC hMAC; CSecureChannelClient *pSCClient; BYTE abTempMAC[WMDM_MAC_LENGTH]; BYTE abMACVerify[WMDM_MAC_LENGTH]; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } g_pSPs[m_wSPIndex]->GetSCClient(&pSCClient); if (!pSCClient) { CORg( E_FAIL ); } CORg( m_pDevice->GetSerialNumber(pSerialNumber, abTempMAC) ); // Verify the MAC from SP CORg( pSCClient->MACInit(&hMAC) ); CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pSerialNumber), sizeof(WMDMID)) ); CORg( pSCClient->MACFinal(hMAC, abMACVerify) ); if (memcmp(abMACVerify, abTempMAC, WMDM_MAC_LENGTH) != 0) { CORg( WMDM_E_MAC_CHECK_FAILED ); } // Compute the MAC to send back to the application CORg( g_pAppSCServer->MACInit(&hMAC) ); CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pSerialNumber), sizeof(WMDMID)) ); CORg( g_pAppSCServer->MACFinal(hMAC, abMac) ); Error: hrLogDWORD("IWMDMDevice::GetSerialNumber returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetPowerSource(DWORD *pdwPowerSource, DWORD *pdwPercentRemaining) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetPowerSource(pdwPowerSource, pdwPercentRemaining) ); Error: hrLogDWORD("IWMDMDevice::GetPowerSource returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetStatus(DWORD *pdwStatus) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetStatus(pdwStatus) ); Error: hrLogDWORD("IWMDMDevice::GetStatus returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::EnumStorage(IWMDMEnumStorage **ppEnumStorage) { HRESULT hr; CComObject *pEnumObj = NULL; IMDSPEnumStorage *pEnumStg = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CARg( ppEnumStorage ); CORg( m_pDevice->EnumStorage(&pEnumStg) ); CORg( CComObject::CreateInstance(&pEnumObj) ); CORg( pEnumObj->QueryInterface(IID_IWMDMEnumStorage, reinterpret_cast(ppEnumStorage)) ); if (FAILED(hr)) { delete pEnumObj; pEnumObj = NULL; goto Error; } pEnumObj->SetContainedPointer(pEnumStg, m_wSPIndex); Error: if(pEnumStg) pEnumStg->Release(); hrLogDWORD("IWMDMDevice::EnumStorage returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetFormatSupport(_WAVEFORMATEX **ppFormatEx, UINT *pnFormatCount, LPWSTR **pppwszMimeType, UINT *pnMimeTypeCount) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetFormatSupport(ppFormatEx, pnFormatCount, pppwszMimeType, pnMimeTypeCount) ); Error: hrLogDWORD("IWMDMDevice::GetFormatSupport returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetDeviceIcon(ULONG *hIcon) { HRESULT hr; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->GetDeviceIcon(hIcon) ); Error: hrLogDWORD("IWMDMDevice::GetDeviceIcon returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::SendOpaqueCommand(OPAQUECOMMAND *pCommand) { HRESULT hr; HMAC hMAC; CSecureChannelClient *pSCClient; BYTE abMACVerify[WMDM_MAC_LENGTH]; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } if( (pCommand == NULL) || ((pCommand->pData == NULL) && (pCommand->dwDataLen > 0)) ) { CORg( E_INVALIDARG ); } // Verify the MAC from APP CORg( g_pAppSCServer->MACInit(&hMAC) ); CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(GUID)) ); CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) ); if (pCommand->pData) { CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) ); } CORg( g_pAppSCServer->MACFinal(hMAC, abMACVerify) ); if (memcmp(abMACVerify, pCommand->abMAC, WMDM_MAC_LENGTH) != 0) { CORg( WMDM_E_MAC_CHECK_FAILED ); } g_pSPs[m_wSPIndex]->GetSCClient(&pSCClient); if (!pSCClient) { CORg( E_FAIL ); } // Compute the MAC to send back to the SP CORg( pSCClient->MACInit(&hMAC) ); CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(GUID)) ); CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) ); if (pCommand->pData) { CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) ); } CORg( pSCClient->MACFinal(hMAC, pCommand->abMAC) ); // Pass the call down to the SP CORg( m_pDevice->SendOpaqueCommand(pCommand) ); // Verify the MAC from SP CORg( pSCClient->MACInit(&hMAC) ); CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(GUID)) ); CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) ); if (pCommand->pData) { CORg( pSCClient->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) ); } CORg( pSCClient->MACFinal(hMAC, abMACVerify) ); if (memcmp(abMACVerify, pCommand->abMAC, WMDM_MAC_LENGTH) != 0) { CORg( WMDM_E_MAC_CHECK_FAILED ); } // Compute the MAC to send back to the application CORg( g_pAppSCServer->MACInit(&hMAC) ); CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->guidCommand)), sizeof(GUID)) ); CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(&(pCommand->dwDataLen)), sizeof(pCommand->dwDataLen)) ); if (pCommand->pData) { CORg( g_pAppSCServer->MACUpdate(hMAC, (BYTE*)(pCommand->pData), pCommand->dwDataLen) ); } CORg( g_pAppSCServer->MACFinal(hMAC, pCommand->abMAC) ); Error: hrLogDWORD("IWMDMDevice::SendOpaqueCommand returned 0x%08lx", hr, hr); return hr; } // IWMDMDevice2 HRESULT CWMDMDevice::GetStorage( LPCWSTR pszStorageName, IWMDMStorage** ppStorage ) { HRESULT hr; IMDSPDevice2* pDev2 = NULL; IMDSPStorage* pMDSPStorageFound = NULL; IMDSPStorage* pMDSubStorage = NULL; CComObject* pStgObj = NULL; CARg( ppStorage ); CARg( pszStorageName ); if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } // Get the Storage pointer from the SP (as a IMDSPStorage) hr = m_pDevice->QueryInterface(IID_IMDSPDevice2, reinterpret_cast(&pDev2)); if( SUCCEEDED(hr) ) { hr = pDev2->GetStorage( pszStorageName, &pMDSPStorageFound ); } // This functionalty is not implemented by the SP. Find the storage by enumerating all storages if( hr == E_NOTIMPL || hr == E_NOINTERFACE ) { IMDSPEnumStorage *pEnum = NULL; WCHAR pswzMDSubStorageName[MAX_PATH]; ULONG ulFetched; CORg(m_pDevice->EnumStorage(&pEnum)); while( S_OK == pEnum->Next(1, &pMDSubStorage, &ulFetched) ) { hr = pMDSubStorage->GetName( pswzMDSubStorageName, MAX_PATH ); if( SUCCEEDED(hr) && ( _wcsicmp( pswzMDSubStorageName, pszStorageName ) == 0 ) ) { // We have found the storage we are looking for. pMDSPStorageFound = pMDSubStorage; break; } pMDSubStorage->Release(); } pEnum->Release(); } // Create a IWMDMStorage object and connect it to the the storage from the SP if( pMDSPStorageFound != NULL ) { CORg( CComObject::CreateInstance(&pStgObj) ); CORg( pStgObj->QueryInterface(IID_IWMDMStorage, reinterpret_cast(ppStorage)) ); pStgObj->SetContainedPointer(pMDSPStorageFound, m_wSPIndex); } // Did not find a matching storage else if( SUCCEEDED(hr) ) { hr = S_FALSE; } Error: if( pDev2 ) pDev2->Release(); if( hr != S_OK ) { ppStorage = NULL; delete pStgObj; } hrLogDWORD("IWMDMDevice2::GetStorage returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetFormatSupport2( DWORD dwFlags, _WAVEFORMATEX **ppAudioFormatEx, UINT *pnAudioFormatCount, _VIDEOINFOHEADER **ppVideoFormatEx, UINT *pnVideoFormatCount, WMFILECAPABILITIES **ppFileType, UINT *pnFileTypeCount) { HRESULT hr = S_OK; IMDSPDevice2* pDev2 = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDevice2, reinterpret_cast(&pDev2)) ); CORg( pDev2->GetFormatSupport2( dwFlags, ppAudioFormatEx, pnAudioFormatCount, ppVideoFormatEx, pnVideoFormatCount, ppFileType, pnFileTypeCount) ); Error: if( pDev2 ) pDev2->Release(); hrLogDWORD("IWMDMDevice2::GetFormatSupport2 returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetSpecifyPropertyPages( ISpecifyPropertyPages** ppSpecifyPropPages, IUnknown*** pppUnknowns, ULONG* pcUnks ) { HRESULT hr = S_OK; IMDSPDevice2* pDev2 = NULL; CARg( ppSpecifyPropPages ); CARg( pppUnknowns ); CARg( pcUnks ); if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDevice2, reinterpret_cast(&pDev2)) ); CORg( pDev2->GetSpecifyPropertyPages( ppSpecifyPropPages, pppUnknowns, pcUnks ) ); Error: if( pDev2 ) pDev2->Release(); hrLogDWORD("IWMDMDevice2::GetSpecifyPropertyPages returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::GetPnPName( LPWSTR pwszPnPName, UINT nMaxChars ) { HRESULT hr = S_OK; IMDSPDevice2* pDev2 = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDevice2, reinterpret_cast(&pDev2)) ); CORg( pDev2->GetPnPName( pwszPnPName, nMaxChars ) ); Error: if( pDev2 ) { pDev2->Release(); } hrLogDWORD("IWMDMDevice2::GetPnPName returned 0x%08lx", hr, hr); return hr; } // IWMDMDeviceControl HRESULT CWMDMDevice::GetCapabilities(DWORD *pdwCapabilitiesMask) { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } if (!pdwCapabilitiesMask) { CORg( E_INVALIDARG ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->GetCapabilities(pdwCapabilitiesMask) ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::GetCapabilities returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Play() { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Play() ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Play returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Record(_WAVEFORMATEX *pFormat) { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } if (!pFormat) { CORg( E_INVALIDARG ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Record(pFormat) ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Record returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Pause() { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Pause() ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Pause returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Resume() { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Resume() ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Resume returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Stop() { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Stop() ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Stop returned 0x%08lx", hr, hr); return hr; } HRESULT CWMDMDevice::Seek(UINT fuMode, int nOffset) { HRESULT hr; IMDSPDeviceControl *pDevCtrl = NULL; if (g_pAppSCServer) { if(!g_pAppSCServer->fIsAuthenticated()) { CORg( WMDM_E_NOTCERTIFIED ); } } else { CORg( E_FAIL ); } CORg( m_pDevice->QueryInterface(IID_IMDSPDeviceControl, reinterpret_cast(&pDevCtrl)) ); CORg( pDevCtrl->Seek(fuMode, nOffset) ); Error: if (pDevCtrl) pDevCtrl->Release(); hrLogDWORD("IWMDMDeviceControl::Seek returned 0x%08lx", hr, hr); return hr; } void CWMDMDevice::SetContainedPointer(IMDSPDevice *pDevice, WORD wSPIndex) { m_pDevice = pDevice; m_pDevice->AddRef(); m_wSPIndex = wSPIndex; return; }