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.
 
 
 
 
 
 

617 lines
15 KiB

// MediaDevMgr.cpp : Implementation of CMediaDevMgr
#include "stdafx.h"
#include "mswmdm.h"
#include "loghelp.h"
#include "MediaDevMgr.h"
#include "WMDMDeviceEnum.h"
#include "SCServer.h"
#include "key.h"
#define STRSAFE_NO_DEPRECATE
#include "strsafe.h"
#define SDK_VERSION 0x00080000
#define WMDM_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager")
#define MDSP_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager\\Plugins\\SP")
#define MDSCP_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager\\Plugins\\SCP")
#define MSSCP_PROGID L"MsScp.MSSCP.1"
#define MSSCP_KEYNAME _T("MSSCP")
/////////////////////////////////////////////////////////////////////////////
// CMediaDevMgr
CSPInfo **g_pSPs = NULL;
WORD g_wSPCount = 0;
CSCPInfo **g_pSCPs = NULL;
WORD g_wSCPCount = 0;
int g_nGlobalRefCount = 0;
CComAutoCriticalSection csGlobal;
CSecureChannelServer *g_pAppSCServer = NULL;
//
// This method is called by objects accessing the global SP, SCP arrays.
// These objects will need to call GlobalAddRef, GlobalRelease so that we
// know when we can unload the plugins.
//
void GlobalAddRef()
{
csGlobal.Lock();
g_nGlobalRefCount ++;
csGlobal.Unlock();
}
void GlobalRelease()
{
csGlobal.Lock();
g_nGlobalRefCount --;
// Check if we can unload SP's, SCP's
if( g_nGlobalRefCount == 0 )
{
int iIndex;
if( g_pSPs )
{
for(iIndex=0;iIndex<g_wSPCount;iIndex++)
delete g_pSPs[iIndex];
delete g_pSPs;
g_pSPs = NULL;
g_wSPCount = 0;
}
if( g_pSCPs )
{
for(iIndex=0;iIndex<g_wSCPCount;iIndex++)
delete g_pSCPs[iIndex];
delete g_pSCPs;
g_pSCPs = NULL;
g_wSCPCount = 0;
}
if( g_pAppSCServer )
{
delete g_pAppSCServer;
g_pAppSCServer = NULL;
}
}
csGlobal.Unlock();
}
CMediaDevMgr::CMediaDevMgr()
{
// Add a refcount to SPs, SCPs
GlobalAddRef();
g_pAppSCServer = new CSecureChannelServer();
if (g_pAppSCServer)
{
g_pAppSCServer->SetCertificate(SAC_CERT_V1, (BYTE*)g_abAppCert, sizeof(g_abAppCert), (BYTE*)g_abPriv, sizeof(g_abPriv));
}
// Do we need to load SP's?
csGlobal.Lock();
if( g_pSPs == NULL )
{
hrLoadSPs();
}
csGlobal.Unlock();
}
CMediaDevMgr::~CMediaDevMgr()
{
// Decrease refcount to SPs, SCPs
GlobalRelease();
}
// Static helper function. The SCP's are loaded on first use for pref.
HRESULT CMediaDevMgr::LoadSCPs()
{
HRESULT hr = S_OK;
csGlobal.Lock();
if(g_pSCPs == NULL)
{
hr = hrLoadSCPs();
}
csGlobal.Unlock();
return hr;
}
HRESULT CMediaDevMgr::hrLoadSPs()
{
USES_CONVERSION;
HRESULT hr;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
LONG lRetVal;
LONG lRetVal2;
DWORD dwSubKeys;
DWORD dwMaxNameLen;
WORD wIndex = 0;
LPTSTR ptszKeyName = NULL;
DWORD dwKeyNameLen;
DWORD dwType;
BYTE pbData[512];
DWORD dwDataLen = 512;
char szMessage[512+64];
lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, MDSP_REG_LOCATION, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hKey);
if (lRetVal != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
// Get the count of Sub-Keys under SP
lRetVal = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (lRetVal != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
dwMaxNameLen++;
// Allocate a buffer to hold the subkey names
ptszKeyName = new TCHAR[dwMaxNameLen];
if (!ptszKeyName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
// Allocate the array of CSPInfo *'s
g_pSPs = new CSPInfo *[dwSubKeys];
if (!g_pSPs)
{
hr = E_OUTOFMEMORY;
goto exit;
}
// Loop through the sub-keys initializing a CSPInfo for each sub key
lRetVal = ERROR_SUCCESS;
while (lRetVal != ERROR_NO_MORE_ITEMS)
{
dwKeyNameLen = dwMaxNameLen;
lRetVal = RegEnumKeyEx(hKey, wIndex, ptszKeyName, &dwKeyNameLen, NULL, NULL, NULL, NULL);
if (lRetVal == ERROR_SUCCESS)
{
lRetVal2 = RegOpenKeyEx(hKey, ptszKeyName, NULL, KEY_QUERY_VALUE, &hSubKey);
if (lRetVal2 != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal2);
goto exit;
}
g_pSPs[g_wSPCount] = new CSPInfo;
if (!g_pSPs[g_wSPCount])
{
hr = E_OUTOFMEMORY;
goto exit;
}
dwDataLen = sizeof(pbData);
lRetVal2 = RegQueryValueEx(hSubKey, _T("ProgID"), NULL, &dwType, pbData, &dwDataLen);
if (lRetVal2 != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal2);
goto exit;
}
strcpy(szMessage, "Loading SP ProgID = ");
hr = StringCbCat(szMessage, sizeof(szMessage), (LPTSTR)pbData);
if(SUCCEEDED(hr) )
{
hrLogString(szMessage, S_OK);
}
hr = g_pSPs[g_wSPCount]->hrInitialize(T2W((LPTSTR)pbData));
if (FAILED(hr))
{
// If this SP didn't initialize then we just try the next one.
delete g_pSPs[g_wSPCount];
}
else
{
// We have added the CSPInfo to the array no inc the counter
g_wSPCount++;
}
RegCloseKey(hSubKey);
hSubKey = NULL;
wIndex++;
}
else if (lRetVal != ERROR_NO_MORE_ITEMS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
}
hr = S_OK;
exit:
if (hKey)
RegCloseKey(hKey);
if (hSubKey)
RegCloseKey(hSubKey);
if (ptszKeyName)
delete [] ptszKeyName;
hrLogDWORD("CMediaDevMgr::hrLoadSPs returned 0x%08lx", hr, hr);
return hr;
}
HRESULT CMediaDevMgr::hrLoadSCPs()
{
USES_CONVERSION;
HRESULT hr;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
LONG lRetVal;
LONG lRetVal2;
DWORD dwSubKeys;
DWORD dwMaxNameLen;
WORD wIndex = 0;
LPTSTR ptszKeyName = NULL;
DWORD dwKeyNameLen;
DWORD dwType;
BYTE pbData[512];
DWORD dwDataLen = 512;
char szMessage[512];
lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, MDSCP_REG_LOCATION, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hKey);
if (lRetVal != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
// Get the count of Sub-Keys under SP
lRetVal = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (lRetVal != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
dwMaxNameLen++;
// Allocate a buffer to hold the subkey names
ptszKeyName = new TCHAR[dwMaxNameLen];
if (!ptszKeyName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
// Allocate the array of CSPInfo *'s
// Add one for our SCP in case someone deleted the reg key
g_pSCPs = new CSCPInfo *[dwSubKeys + 1];
if (!g_pSCPs)
{
hr = E_OUTOFMEMORY;
goto exit;
}
// WARNING:
// We are hard coding the loading of the MSSCP as
// the first SCP in the system. This will always load
// as the first SCP in the array so that our SCP
// will always get first dibs on WMA content
g_pSCPs[g_wSCPCount] = new CSCPInfo;
if (!g_pSCPs[g_wSCPCount])
{
hr = E_OUTOFMEMORY;
goto exit;
}
strcpy(szMessage, "Loading MSSCP");
hrLogString(szMessage, S_OK);
hr = g_pSCPs[g_wSCPCount]->hrInitialize(MSSCP_PROGID);
if (FAILED(hr))
{
// If this SCP didn't initialize then we just try the next one.
delete g_pSCPs[g_wSCPCount];
}
else
{
// We have added the CSPInfo to the array no inc the counter
g_wSCPCount++;
}
// Loop through the sub-keys initializing a CSPInfo for each sub key
lRetVal = ERROR_SUCCESS;
while (lRetVal != ERROR_NO_MORE_ITEMS)
{
dwKeyNameLen = dwMaxNameLen;
lRetVal = RegEnumKeyEx(hKey, wIndex, ptszKeyName, &dwKeyNameLen, NULL, NULL, NULL, NULL);
if (lRetVal == ERROR_SUCCESS)
{
lRetVal2 = RegOpenKeyEx(hKey, ptszKeyName, NULL, KEY_QUERY_VALUE, &hSubKey);
if (lRetVal2 != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal2);
goto exit;
}
// If this is the MSSCP then skip it because we already loaded it.
if (_tcscmp(MSSCP_KEYNAME, ptszKeyName) == 0)
{
wIndex++;
continue;
}
g_pSCPs[g_wSCPCount] = new CSCPInfo;
if (!g_pSCPs[g_wSCPCount])
{
hr = E_OUTOFMEMORY;
goto exit;
}
dwDataLen = sizeof(pbData);
lRetVal2 = RegQueryValueEx(hSubKey, _T("ProgID"), NULL, &dwType, pbData, &dwDataLen);
if (lRetVal2 != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lRetVal2);
goto exit;
}
strcpy(szMessage, "Loading SCP ProgID = ");
hr = StringCbCat(szMessage, sizeof(szMessage), (LPTSTR)pbData);
if(SUCCEEDED(hr))
{
hrLogString(szMessage, S_OK);
}
hr = g_pSCPs[g_wSCPCount]->hrInitialize(T2W((LPTSTR)pbData));
if (FAILED(hr))
{
// If this SCP didn't initialize then we just try the next one.
delete g_pSCPs[g_wSCPCount];
}
else
{
// We have added the CSPInfo to the array no inc the counter
g_wSCPCount++;
}
RegCloseKey(hSubKey);
hSubKey = NULL;
wIndex++;
}
else if (lRetVal != ERROR_NO_MORE_ITEMS)
{
hr = HRESULT_FROM_WIN32(lRetVal);
goto exit;
}
}
hr = S_OK;
exit:
if (hKey)
RegCloseKey(hKey);
if (hSubKey)
RegCloseKey(hSubKey);
if (ptszKeyName)
delete [] ptszKeyName;
hrLogDWORD("CMediaDevMgr::hrLoadSCPs returned 0x%08lx", hr, hr);
return hr;
}
// IWMDeviceManager Methods
HRESULT CMediaDevMgr::GetRevision(DWORD *pdwRevision)
{
HRESULT hr;
if (g_pAppSCServer)
{
if(!g_pAppSCServer->fIsAuthenticated())
{
hr = WMDM_E_NOTCERTIFIED;
goto exit;
}
}
else
{
hr = E_FAIL;
goto exit;
}
if (!pdwRevision)
{
hr = E_INVALIDARG;
goto exit;
}
*pdwRevision = SDK_VERSION;
hr = S_OK;
exit:
hrLogDWORD("IWMDeviceManager::GetRevision returned 0x%08lx", hr, hr);
return hr;
}
HRESULT CMediaDevMgr::GetDeviceCount(DWORD *pdwCount)
{
HRESULT hr;
DWORD dwTotalDevCount = 0;
DWORD dwDevCount;
IMDServiceProvider *pProv = NULL;
WORD x;
if (g_pAppSCServer)
{
if(!g_pAppSCServer->fIsAuthenticated())
{
hr = WMDM_E_NOTCERTIFIED;
goto exit;
}
}
else
{
hr = E_FAIL;
goto exit;
}
if (!pdwCount)
{
hr = E_INVALIDARG;
goto exit;
}
for (x=0;x<g_wSPCount;x++)
{
hr = g_pSPs[x]->hrGetInterface(&pProv);
if (FAILED(hr))
{
goto exit;
}
hr = pProv->GetDeviceCount(&dwDevCount);
if (FAILED(hr))
{
goto exit;
}
dwTotalDevCount += dwDevCount;
pProv->Release();
pProv = NULL;
}
*pdwCount = dwTotalDevCount;
hr = S_OK;
exit:
if (pProv)
pProv->Release();
hrLogDWORD("IWMDeviceManager::GetDeviceCount returned 0x%08lx", hr, hr);
return hr;
}
HRESULT CMediaDevMgr::EnumDevices(IWMDMEnumDevice **ppEnumDevice)
{
HRESULT hr;
CComObject<CWMDMDeviceEnum> *pEnumObj;
if (g_pAppSCServer)
{
if(!g_pAppSCServer->fIsAuthenticated())
{
hr = WMDM_E_NOTCERTIFIED;
goto exit;
}
}
else
{
hr = E_FAIL;
goto exit;
}
if (!ppEnumDevice)
{
hr = E_INVALIDARG;
goto exit;
}
hr = CComObject<CWMDMDeviceEnum>::CreateInstance(&pEnumObj);
if (FAILED(hr))
{
goto exit;
}
hr = pEnumObj->QueryInterface(IID_IWMDMEnumDevice, reinterpret_cast<void**>(ppEnumDevice));
if (FAILED(hr))
{
delete pEnumObj;
goto exit;
}
exit:
hrLogDWORD("IWMDeviceManager::EnumDevices returned 0x%08lx", hr, hr);
return hr;
}
// IWMDeviceManager2 Methods
HRESULT CMediaDevMgr::GetDeviceFromPnPName( LPCWSTR pwszPnPName, IWMDMDevice** ppDevice )
{
return E_NOTIMPL;
}
HRESULT CMediaDevMgr::SACAuth(DWORD dwProtocolID,
DWORD dwPass,
BYTE *pbDataIn,
DWORD dwDataInLen,
BYTE **ppbDataOut,
DWORD *pdwDataOutLen)
{
HRESULT hr;
if (g_pAppSCServer)
hr = g_pAppSCServer->SACAuth(dwProtocolID, dwPass, pbDataIn, dwDataInLen, ppbDataOut, pdwDataOutLen);
else
hr = E_FAIL;
hrLogDWORD("IComponentAuthenticate::SACAuth returned 0x%08lx", hr, hr);
return hr;
}
HRESULT CMediaDevMgr::SACGetProtocols(DWORD **ppdwProtocols,
DWORD *pdwProtocolCount)
{
HRESULT hr;
if (g_pAppSCServer)
hr = g_pAppSCServer->SACGetProtocols(ppdwProtocols, pdwProtocolCount);
else
hr = E_FAIL;
hrLogDWORD("IComponentAuthenticate::SACGetProtocols returned 0x%08lx", hr, hr);
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CMediaDevMgrClassFactory -
//
// Purpose : THis is used so that the Shell team can use WMDM in the "Both"
// threading model while WMP uses us via the Free threading model. This
// class factory implementation simply delagates and uses the old class factory
// of MediaDevMgr ONLY IF the new CLSID was used to CoCreate WMDM.
//
STDMETHODIMP CMediaDevMgrClassFactory::CreateInstance(IUnknown * pUnkOuter, REFIID riid, void ** ppvObject)
{
HRESULT hr = S_OK;
CComPtr<IClassFactory> spClassFactory;
hr = _Module.GetClassObject( CLSID_MediaDevMgr, __uuidof(IClassFactory), (LPVOID *)&spClassFactory );
if( SUCCEEDED( hr ) )
{
hr = spClassFactory->CreateInstance( pUnkOuter, riid, ppvObject );
}
return( hr );
}
STDMETHODIMP CMediaDevMgrClassFactory::LockServer(BOOL fLock)
{
fLock ? _Module.Lock() : _Module.Unlock();
return( S_OK );
}