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

  1. // MediaDevMgr.cpp : Implementation of CMediaDevMgr
  2. #include "stdafx.h"
  3. #include "mswmdm.h"
  4. #include "loghelp.h"
  5. #include "MediaDevMgr.h"
  6. #include "WMDMDeviceEnum.h"
  7. #include "SCServer.h"
  8. #include "key.h"
  9. #define STRSAFE_NO_DEPRECATE
  10. #include "strsafe.h"
  11. #define SDK_VERSION 0x00080000
  12. #define WMDM_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager")
  13. #define MDSP_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager\\Plugins\\SP")
  14. #define MDSCP_REG_LOCATION _T("Software\\Microsoft\\Windows Media Device Manager\\Plugins\\SCP")
  15. #define MSSCP_PROGID L"MsScp.MSSCP.1"
  16. #define MSSCP_KEYNAME _T("MSSCP")
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CMediaDevMgr
  19. CSPInfo **g_pSPs = NULL;
  20. WORD g_wSPCount = 0;
  21. CSCPInfo **g_pSCPs = NULL;
  22. WORD g_wSCPCount = 0;
  23. int g_nGlobalRefCount = 0;
  24. CComAutoCriticalSection csGlobal;
  25. CSecureChannelServer *g_pAppSCServer = NULL;
  26. //
  27. // This method is called by objects accessing the global SP, SCP arrays.
  28. // These objects will need to call GlobalAddRef, GlobalRelease so that we
  29. // know when we can unload the plugins.
  30. //
  31. void GlobalAddRef()
  32. {
  33. csGlobal.Lock();
  34. g_nGlobalRefCount ++;
  35. csGlobal.Unlock();
  36. }
  37. void GlobalRelease()
  38. {
  39. csGlobal.Lock();
  40. g_nGlobalRefCount --;
  41. // Check if we can unload SP's, SCP's
  42. if( g_nGlobalRefCount == 0 )
  43. {
  44. int iIndex;
  45. if( g_pSPs )
  46. {
  47. for(iIndex=0;iIndex<g_wSPCount;iIndex++)
  48. delete g_pSPs[iIndex];
  49. delete g_pSPs;
  50. g_pSPs = NULL;
  51. g_wSPCount = 0;
  52. }
  53. if( g_pSCPs )
  54. {
  55. for(iIndex=0;iIndex<g_wSCPCount;iIndex++)
  56. delete g_pSCPs[iIndex];
  57. delete g_pSCPs;
  58. g_pSCPs = NULL;
  59. g_wSCPCount = 0;
  60. }
  61. if( g_pAppSCServer )
  62. {
  63. delete g_pAppSCServer;
  64. g_pAppSCServer = NULL;
  65. }
  66. }
  67. csGlobal.Unlock();
  68. }
  69. CMediaDevMgr::CMediaDevMgr()
  70. {
  71. // Add a refcount to SPs, SCPs
  72. GlobalAddRef();
  73. g_pAppSCServer = new CSecureChannelServer();
  74. if (g_pAppSCServer)
  75. {
  76. g_pAppSCServer->SetCertificate(SAC_CERT_V1, (BYTE*)g_abAppCert, sizeof(g_abAppCert), (BYTE*)g_abPriv, sizeof(g_abPriv));
  77. }
  78. // Do we need to load SP's?
  79. csGlobal.Lock();
  80. if( g_pSPs == NULL )
  81. {
  82. hrLoadSPs();
  83. }
  84. csGlobal.Unlock();
  85. }
  86. CMediaDevMgr::~CMediaDevMgr()
  87. {
  88. // Decrease refcount to SPs, SCPs
  89. GlobalRelease();
  90. }
  91. // Static helper function. The SCP's are loaded on first use for pref.
  92. HRESULT CMediaDevMgr::LoadSCPs()
  93. {
  94. HRESULT hr = S_OK;
  95. csGlobal.Lock();
  96. if(g_pSCPs == NULL)
  97. {
  98. hr = hrLoadSCPs();
  99. }
  100. csGlobal.Unlock();
  101. return hr;
  102. }
  103. HRESULT CMediaDevMgr::hrLoadSPs()
  104. {
  105. USES_CONVERSION;
  106. HRESULT hr;
  107. HKEY hKey = NULL;
  108. HKEY hSubKey = NULL;
  109. LONG lRetVal;
  110. LONG lRetVal2;
  111. DWORD dwSubKeys;
  112. DWORD dwMaxNameLen;
  113. WORD wIndex = 0;
  114. LPTSTR ptszKeyName = NULL;
  115. DWORD dwKeyNameLen;
  116. DWORD dwType;
  117. BYTE pbData[512];
  118. DWORD dwDataLen = 512;
  119. char szMessage[512+64];
  120. lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, MDSP_REG_LOCATION, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hKey);
  121. if (lRetVal != ERROR_SUCCESS)
  122. {
  123. hr = HRESULT_FROM_WIN32(lRetVal);
  124. goto exit;
  125. }
  126. // Get the count of Sub-Keys under SP
  127. lRetVal = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
  128. if (lRetVal != ERROR_SUCCESS)
  129. {
  130. hr = HRESULT_FROM_WIN32(lRetVal);
  131. goto exit;
  132. }
  133. dwMaxNameLen++;
  134. // Allocate a buffer to hold the subkey names
  135. ptszKeyName = new TCHAR[dwMaxNameLen];
  136. if (!ptszKeyName)
  137. {
  138. hr = E_OUTOFMEMORY;
  139. goto exit;
  140. }
  141. // Allocate the array of CSPInfo *'s
  142. g_pSPs = new CSPInfo *[dwSubKeys];
  143. if (!g_pSPs)
  144. {
  145. hr = E_OUTOFMEMORY;
  146. goto exit;
  147. }
  148. // Loop through the sub-keys initializing a CSPInfo for each sub key
  149. lRetVal = ERROR_SUCCESS;
  150. while (lRetVal != ERROR_NO_MORE_ITEMS)
  151. {
  152. dwKeyNameLen = dwMaxNameLen;
  153. lRetVal = RegEnumKeyEx(hKey, wIndex, ptszKeyName, &dwKeyNameLen, NULL, NULL, NULL, NULL);
  154. if (lRetVal == ERROR_SUCCESS)
  155. {
  156. lRetVal2 = RegOpenKeyEx(hKey, ptszKeyName, NULL, KEY_QUERY_VALUE, &hSubKey);
  157. if (lRetVal2 != ERROR_SUCCESS)
  158. {
  159. hr = HRESULT_FROM_WIN32(lRetVal2);
  160. goto exit;
  161. }
  162. g_pSPs[g_wSPCount] = new CSPInfo;
  163. if (!g_pSPs[g_wSPCount])
  164. {
  165. hr = E_OUTOFMEMORY;
  166. goto exit;
  167. }
  168. dwDataLen = sizeof(pbData);
  169. lRetVal2 = RegQueryValueEx(hSubKey, _T("ProgID"), NULL, &dwType, pbData, &dwDataLen);
  170. if (lRetVal2 != ERROR_SUCCESS)
  171. {
  172. hr = HRESULT_FROM_WIN32(lRetVal2);
  173. goto exit;
  174. }
  175. strcpy(szMessage, "Loading SP ProgID = ");
  176. hr = StringCbCat(szMessage, sizeof(szMessage), (LPTSTR)pbData);
  177. if(SUCCEEDED(hr) )
  178. {
  179. hrLogString(szMessage, S_OK);
  180. }
  181. hr = g_pSPs[g_wSPCount]->hrInitialize(T2W((LPTSTR)pbData));
  182. if (FAILED(hr))
  183. {
  184. // If this SP didn't initialize then we just try the next one.
  185. delete g_pSPs[g_wSPCount];
  186. }
  187. else
  188. {
  189. // We have added the CSPInfo to the array no inc the counter
  190. g_wSPCount++;
  191. }
  192. RegCloseKey(hSubKey);
  193. hSubKey = NULL;
  194. wIndex++;
  195. }
  196. else if (lRetVal != ERROR_NO_MORE_ITEMS)
  197. {
  198. hr = HRESULT_FROM_WIN32(lRetVal);
  199. goto exit;
  200. }
  201. }
  202. hr = S_OK;
  203. exit:
  204. if (hKey)
  205. RegCloseKey(hKey);
  206. if (hSubKey)
  207. RegCloseKey(hSubKey);
  208. if (ptszKeyName)
  209. delete [] ptszKeyName;
  210. hrLogDWORD("CMediaDevMgr::hrLoadSPs returned 0x%08lx", hr, hr);
  211. return hr;
  212. }
  213. HRESULT CMediaDevMgr::hrLoadSCPs()
  214. {
  215. USES_CONVERSION;
  216. HRESULT hr;
  217. HKEY hKey = NULL;
  218. HKEY hSubKey = NULL;
  219. LONG lRetVal;
  220. LONG lRetVal2;
  221. DWORD dwSubKeys;
  222. DWORD dwMaxNameLen;
  223. WORD wIndex = 0;
  224. LPTSTR ptszKeyName = NULL;
  225. DWORD dwKeyNameLen;
  226. DWORD dwType;
  227. BYTE pbData[512];
  228. DWORD dwDataLen = 512;
  229. char szMessage[512];
  230. lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, MDSCP_REG_LOCATION, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hKey);
  231. if (lRetVal != ERROR_SUCCESS)
  232. {
  233. hr = HRESULT_FROM_WIN32(lRetVal);
  234. goto exit;
  235. }
  236. // Get the count of Sub-Keys under SP
  237. lRetVal = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
  238. if (lRetVal != ERROR_SUCCESS)
  239. {
  240. hr = HRESULT_FROM_WIN32(lRetVal);
  241. goto exit;
  242. }
  243. dwMaxNameLen++;
  244. // Allocate a buffer to hold the subkey names
  245. ptszKeyName = new TCHAR[dwMaxNameLen];
  246. if (!ptszKeyName)
  247. {
  248. hr = E_OUTOFMEMORY;
  249. goto exit;
  250. }
  251. // Allocate the array of CSPInfo *'s
  252. // Add one for our SCP in case someone deleted the reg key
  253. g_pSCPs = new CSCPInfo *[dwSubKeys + 1];
  254. if (!g_pSCPs)
  255. {
  256. hr = E_OUTOFMEMORY;
  257. goto exit;
  258. }
  259. // WARNING:
  260. // We are hard coding the loading of the MSSCP as
  261. // the first SCP in the system. This will always load
  262. // as the first SCP in the array so that our SCP
  263. // will always get first dibs on WMA content
  264. g_pSCPs[g_wSCPCount] = new CSCPInfo;
  265. if (!g_pSCPs[g_wSCPCount])
  266. {
  267. hr = E_OUTOFMEMORY;
  268. goto exit;
  269. }
  270. strcpy(szMessage, "Loading MSSCP");
  271. hrLogString(szMessage, S_OK);
  272. hr = g_pSCPs[g_wSCPCount]->hrInitialize(MSSCP_PROGID);
  273. if (FAILED(hr))
  274. {
  275. // If this SCP didn't initialize then we just try the next one.
  276. delete g_pSCPs[g_wSCPCount];
  277. }
  278. else
  279. {
  280. // We have added the CSPInfo to the array no inc the counter
  281. g_wSCPCount++;
  282. }
  283. // Loop through the sub-keys initializing a CSPInfo for each sub key
  284. lRetVal = ERROR_SUCCESS;
  285. while (lRetVal != ERROR_NO_MORE_ITEMS)
  286. {
  287. dwKeyNameLen = dwMaxNameLen;
  288. lRetVal = RegEnumKeyEx(hKey, wIndex, ptszKeyName, &dwKeyNameLen, NULL, NULL, NULL, NULL);
  289. if (lRetVal == ERROR_SUCCESS)
  290. {
  291. lRetVal2 = RegOpenKeyEx(hKey, ptszKeyName, NULL, KEY_QUERY_VALUE, &hSubKey);
  292. if (lRetVal2 != ERROR_SUCCESS)
  293. {
  294. hr = HRESULT_FROM_WIN32(lRetVal2);
  295. goto exit;
  296. }
  297. // If this is the MSSCP then skip it because we already loaded it.
  298. if (_tcscmp(MSSCP_KEYNAME, ptszKeyName) == 0)
  299. {
  300. wIndex++;
  301. continue;
  302. }
  303. g_pSCPs[g_wSCPCount] = new CSCPInfo;
  304. if (!g_pSCPs[g_wSCPCount])
  305. {
  306. hr = E_OUTOFMEMORY;
  307. goto exit;
  308. }
  309. dwDataLen = sizeof(pbData);
  310. lRetVal2 = RegQueryValueEx(hSubKey, _T("ProgID"), NULL, &dwType, pbData, &dwDataLen);
  311. if (lRetVal2 != ERROR_SUCCESS)
  312. {
  313. hr = HRESULT_FROM_WIN32(lRetVal2);
  314. goto exit;
  315. }
  316. strcpy(szMessage, "Loading SCP ProgID = ");
  317. hr = StringCbCat(szMessage, sizeof(szMessage), (LPTSTR)pbData);
  318. if(SUCCEEDED(hr))
  319. {
  320. hrLogString(szMessage, S_OK);
  321. }
  322. hr = g_pSCPs[g_wSCPCount]->hrInitialize(T2W((LPTSTR)pbData));
  323. if (FAILED(hr))
  324. {
  325. // If this SCP didn't initialize then we just try the next one.
  326. delete g_pSCPs[g_wSCPCount];
  327. }
  328. else
  329. {
  330. // We have added the CSPInfo to the array no inc the counter
  331. g_wSCPCount++;
  332. }
  333. RegCloseKey(hSubKey);
  334. hSubKey = NULL;
  335. wIndex++;
  336. }
  337. else if (lRetVal != ERROR_NO_MORE_ITEMS)
  338. {
  339. hr = HRESULT_FROM_WIN32(lRetVal);
  340. goto exit;
  341. }
  342. }
  343. hr = S_OK;
  344. exit:
  345. if (hKey)
  346. RegCloseKey(hKey);
  347. if (hSubKey)
  348. RegCloseKey(hSubKey);
  349. if (ptszKeyName)
  350. delete [] ptszKeyName;
  351. hrLogDWORD("CMediaDevMgr::hrLoadSCPs returned 0x%08lx", hr, hr);
  352. return hr;
  353. }
  354. // IWMDeviceManager Methods
  355. HRESULT CMediaDevMgr::GetRevision(DWORD *pdwRevision)
  356. {
  357. HRESULT hr;
  358. if (g_pAppSCServer)
  359. {
  360. if(!g_pAppSCServer->fIsAuthenticated())
  361. {
  362. hr = WMDM_E_NOTCERTIFIED;
  363. goto exit;
  364. }
  365. }
  366. else
  367. {
  368. hr = E_FAIL;
  369. goto exit;
  370. }
  371. if (!pdwRevision)
  372. {
  373. hr = E_INVALIDARG;
  374. goto exit;
  375. }
  376. *pdwRevision = SDK_VERSION;
  377. hr = S_OK;
  378. exit:
  379. hrLogDWORD("IWMDeviceManager::GetRevision returned 0x%08lx", hr, hr);
  380. return hr;
  381. }
  382. HRESULT CMediaDevMgr::GetDeviceCount(DWORD *pdwCount)
  383. {
  384. HRESULT hr;
  385. DWORD dwTotalDevCount = 0;
  386. DWORD dwDevCount;
  387. IMDServiceProvider *pProv = NULL;
  388. WORD x;
  389. if (g_pAppSCServer)
  390. {
  391. if(!g_pAppSCServer->fIsAuthenticated())
  392. {
  393. hr = WMDM_E_NOTCERTIFIED;
  394. goto exit;
  395. }
  396. }
  397. else
  398. {
  399. hr = E_FAIL;
  400. goto exit;
  401. }
  402. if (!pdwCount)
  403. {
  404. hr = E_INVALIDARG;
  405. goto exit;
  406. }
  407. for (x=0;x<g_wSPCount;x++)
  408. {
  409. hr = g_pSPs[x]->hrGetInterface(&pProv);
  410. if (FAILED(hr))
  411. {
  412. goto exit;
  413. }
  414. hr = pProv->GetDeviceCount(&dwDevCount);
  415. if (FAILED(hr))
  416. {
  417. goto exit;
  418. }
  419. dwTotalDevCount += dwDevCount;
  420. pProv->Release();
  421. pProv = NULL;
  422. }
  423. *pdwCount = dwTotalDevCount;
  424. hr = S_OK;
  425. exit:
  426. if (pProv)
  427. pProv->Release();
  428. hrLogDWORD("IWMDeviceManager::GetDeviceCount returned 0x%08lx", hr, hr);
  429. return hr;
  430. }
  431. HRESULT CMediaDevMgr::EnumDevices(IWMDMEnumDevice **ppEnumDevice)
  432. {
  433. HRESULT hr;
  434. CComObject<CWMDMDeviceEnum> *pEnumObj;
  435. if (g_pAppSCServer)
  436. {
  437. if(!g_pAppSCServer->fIsAuthenticated())
  438. {
  439. hr = WMDM_E_NOTCERTIFIED;
  440. goto exit;
  441. }
  442. }
  443. else
  444. {
  445. hr = E_FAIL;
  446. goto exit;
  447. }
  448. if (!ppEnumDevice)
  449. {
  450. hr = E_INVALIDARG;
  451. goto exit;
  452. }
  453. hr = CComObject<CWMDMDeviceEnum>::CreateInstance(&pEnumObj);
  454. if (FAILED(hr))
  455. {
  456. goto exit;
  457. }
  458. hr = pEnumObj->QueryInterface(IID_IWMDMEnumDevice, reinterpret_cast<void**>(ppEnumDevice));
  459. if (FAILED(hr))
  460. {
  461. delete pEnumObj;
  462. goto exit;
  463. }
  464. exit:
  465. hrLogDWORD("IWMDeviceManager::EnumDevices returned 0x%08lx", hr, hr);
  466. return hr;
  467. }
  468. // IWMDeviceManager2 Methods
  469. HRESULT CMediaDevMgr::GetDeviceFromPnPName( LPCWSTR pwszPnPName, IWMDMDevice** ppDevice )
  470. {
  471. return E_NOTIMPL;
  472. }
  473. HRESULT CMediaDevMgr::SACAuth(DWORD dwProtocolID,
  474. DWORD dwPass,
  475. BYTE *pbDataIn,
  476. DWORD dwDataInLen,
  477. BYTE **ppbDataOut,
  478. DWORD *pdwDataOutLen)
  479. {
  480. HRESULT hr;
  481. if (g_pAppSCServer)
  482. hr = g_pAppSCServer->SACAuth(dwProtocolID, dwPass, pbDataIn, dwDataInLen, ppbDataOut, pdwDataOutLen);
  483. else
  484. hr = E_FAIL;
  485. hrLogDWORD("IComponentAuthenticate::SACAuth returned 0x%08lx", hr, hr);
  486. return hr;
  487. }
  488. HRESULT CMediaDevMgr::SACGetProtocols(DWORD **ppdwProtocols,
  489. DWORD *pdwProtocolCount)
  490. {
  491. HRESULT hr;
  492. if (g_pAppSCServer)
  493. hr = g_pAppSCServer->SACGetProtocols(ppdwProtocols, pdwProtocolCount);
  494. else
  495. hr = E_FAIL;
  496. hrLogDWORD("IComponentAuthenticate::SACGetProtocols returned 0x%08lx", hr, hr);
  497. return hr;
  498. }
  499. /////////////////////////////////////////////////////////////////////////////
  500. // CMediaDevMgrClassFactory -
  501. //
  502. // Purpose : THis is used so that the Shell team can use WMDM in the "Both"
  503. // threading model while WMP uses us via the Free threading model. This
  504. // class factory implementation simply delagates and uses the old class factory
  505. // of MediaDevMgr ONLY IF the new CLSID was used to CoCreate WMDM.
  506. //
  507. STDMETHODIMP CMediaDevMgrClassFactory::CreateInstance(IUnknown * pUnkOuter, REFIID riid, void ** ppvObject)
  508. {
  509. HRESULT hr = S_OK;
  510. CComPtr<IClassFactory> spClassFactory;
  511. hr = _Module.GetClassObject( CLSID_MediaDevMgr, __uuidof(IClassFactory), (LPVOID *)&spClassFactory );
  512. if( SUCCEEDED( hr ) )
  513. {
  514. hr = spClassFactory->CreateInstance( pUnkOuter, riid, ppvObject );
  515. }
  516. return( hr );
  517. }
  518. STDMETHODIMP CMediaDevMgrClassFactory::LockServer(BOOL fLock)
  519. {
  520. fLock ? _Module.Lock() : _Module.Unlock();
  521. return( S_OK );
  522. }