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.

985 lines
30 KiB

  1. /* mme.cpp
  2. * Handles pnp, etc. for MME APIs
  3. * Created by FrankYe on 2/14/2001
  4. * Copyright (c) 2001-2001 Microsoft Corporation
  5. */
  6. #include <nt.h>
  7. #include <ntrtl.h>
  8. #include <nturtl.h>
  9. #include <windows.h>
  10. #include <regstr.h>
  11. #include <mmsystem.h>
  12. #include <mmsysp.h>
  13. #include <ks.h>
  14. #include <ksmedia.h>
  15. #include <setupapi.h>
  16. #include "debug.h"
  17. #include "reg.h"
  18. #include "service.h"
  19. #include "audiosrv.h"
  20. //=============================================================================
  21. //=== file scope constants ===
  22. //=============================================================================
  23. #define REGSTR_VAL_SETUPPREFERREDAUDIODEVICES TEXT("SetupPreferredAudioDevices")
  24. #define REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT TEXT("SetupPreferredAudioDevicesCount")
  25. #define PNPINFOSIZE (256 * 1024)
  26. //=============================================================================
  27. //=== file scope globals ===
  28. //=============================================================================
  29. RTL_RESOURCE PnpInfoResource;
  30. BOOL gfPnpInfoResource = FALSE;
  31. HANDLE hPnpInfo = NULL;
  32. PMMPNPINFO pPnpInfo = NULL;
  33. //=============================================================================
  34. //=== security helpers ===
  35. //=============================================================================
  36. PSECURITY_DESCRIPTOR BuildSecurityDescriptor(DWORD AccessMask)
  37. {
  38. PSECURITY_DESCRIPTOR pSd;
  39. PSID pSidSystem;
  40. PSID pSidEveryone;
  41. PACL pDacl;
  42. ULONG cbDacl;
  43. BOOL fSuccess;
  44. BOOL f;
  45. SID_IDENTIFIER_AUTHORITY AuthorityNt = SECURITY_NT_AUTHORITY;
  46. SID_IDENTIFIER_AUTHORITY AuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
  47. fSuccess = FALSE;
  48. pSd = HeapAlloc(hHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
  49. if (pSd)
  50. {
  51. if (InitializeSecurityDescriptor(pSd, SECURITY_DESCRIPTOR_REVISION))
  52. {
  53. if (AllocateAndInitializeSid(&AuthorityNt, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSystem))
  54. {
  55. ASSERT(IsValidSid(pSidSystem));
  56. if (AllocateAndInitializeSid(&AuthorityWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone))
  57. {
  58. ASSERT(IsValidSid(pSidEveryone));
  59. cbDacl = sizeof(ACL) +
  60. 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
  61. GetLengthSid(pSidSystem) +
  62. GetLengthSid(pSidEveryone);
  63. pDacl = (PACL)HeapAlloc(hHeap, 0, cbDacl);
  64. if (pDacl) {
  65. if (InitializeAcl(pDacl, cbDacl, ACL_REVISION))
  66. {
  67. if (AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_ALL, pSidSystem))
  68. {
  69. if (AddAccessAllowedAce(pDacl, ACL_REVISION, AccessMask, pSidEveryone))
  70. {
  71. if (SetSecurityDescriptorDacl(pSd, TRUE, pDacl, FALSE))
  72. {
  73. fSuccess = TRUE;
  74. } else {
  75. dprintf(TEXT("BuildSD: SetSecurityDescriptorDacl failed\n"));
  76. }
  77. } else {
  78. dprintf(TEXT("BuildSD: AddAccessAlloweAce for Everyone failed\n"));
  79. }
  80. } else {
  81. dprintf(TEXT("BuildSD: AddAccessAllowedAce for System failed\n"));
  82. }
  83. } else {
  84. dprintf(TEXT("BuildSD: InitializeAcl failed\n"));
  85. }
  86. if (!fSuccess) {
  87. f = HeapFree(hHeap, 0, pDacl);
  88. ASSERT(f);
  89. }
  90. }
  91. FreeSid(pSidEveryone);
  92. } else {
  93. dprintf(TEXT("BuildSD: AllocateAndInitizeSid failed for Everyone\n"));
  94. }
  95. FreeSid(pSidSystem);
  96. } else {
  97. dprintf(TEXT("BuildSD: AllocateAndInitizeSid failed for System\n"));
  98. }
  99. } else {
  100. dprintf(TEXT("BuildSD: InitializeSecurityDescriptor failed\n"));
  101. }
  102. if (!fSuccess) {
  103. f = HeapFree(hHeap, 0, pSd);
  104. ASSERT(f);
  105. }
  106. }
  107. return fSuccess ? pSd : NULL;
  108. }
  109. void DestroySecurityDescriptor(PSECURITY_DESCRIPTOR pSd)
  110. {
  111. PACL pDacl;
  112. BOOL fDaclPresent;
  113. BOOL fDaclDefaulted;
  114. BOOL f;
  115. if (GetSecurityDescriptorDacl(pSd, &fDaclPresent, &pDacl, &fDaclDefaulted))
  116. {
  117. if (fDaclPresent)
  118. {
  119. f = HeapFree(hHeap, 0, pDacl);
  120. ASSERT(f);
  121. }
  122. } else {
  123. dprintf(TEXT("DestroySD: GetSecurityDescriptorDacl failed\n"));
  124. }
  125. f = HeapFree(hHeap, 0, pSd);
  126. ASSERT(f);
  127. return;
  128. }
  129. //=============================================================================
  130. //=== ===
  131. //=============================================================================
  132. //--------------------------------------------------------------------------;
  133. //
  134. // PTSTR BroadcastWinmmDeviceChange
  135. //
  136. // Arguments:
  137. //
  138. // Return value:
  139. //
  140. // History:
  141. // 11/9/98 FrankYe Created
  142. // 2/15/2001 FrankYe Moved from winmm to audiosrv
  143. //
  144. //--------------------------------------------------------------------------;
  145. void BroadcastWinmmDeviceChange(void)
  146. {
  147. static UINT uWinmmDeviceChange = 0;
  148. if (!uWinmmDeviceChange) {
  149. uWinmmDeviceChange = RegisterWindowMessage(WINMMDEVICECHANGEMSGSTRING);
  150. // dprintf(TEXT("BroadcastWinmmDeviceChange: WINMMDEVICECHANGEMSG = %d\n"), uWinmmDeviceChange);
  151. if (!uWinmmDeviceChange) {
  152. dprintf(TEXT("BroadcastWinmmDeviceChange: RegisterWindowMessage failed!\n"));
  153. }
  154. }
  155. if (uWinmmDeviceChange) {
  156. DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  157. long result;
  158. // dprintf(TEXT("BroadcastWinmmDeviceChange: BroadcastSystemMessage\n"));
  159. result = BroadcastSystemMessage(BSF_POSTMESSAGE, &dwRecipients,
  160. uWinmmDeviceChange, 0, 0);
  161. if (result < 0) {
  162. dprintf(TEXT("BroadcastWinmmDeviceChange: BroadcastSystemMessage failed\n"));
  163. }
  164. }
  165. return;
  166. }
  167. //--------------------------------------------------------------------------;
  168. //
  169. // PTSTR MakeRendererDeviceInstanceIdFromDeviceInterface
  170. //
  171. // Arguments:
  172. //
  173. // Return value:
  174. //
  175. // History:
  176. // 11/9/98 FrankYe Created
  177. //
  178. //--------------------------------------------------------------------------;
  179. PTSTR MakeRendererDeviceInstanceIdFromDeviceInterface(PWSTR DeviceInterface)
  180. {
  181. PTSTR DeviceInstanceId;
  182. HDEVINFO hdi;
  183. DWORD dwLastError;
  184. // dprintf(TEXT("MRDIIFDI: DeviceInterface=%ls\n"), DeviceInterface);
  185. DeviceInstanceId = NULL;
  186. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  187. if (INVALID_HANDLE_VALUE != hdi)
  188. {
  189. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  190. // dprintf(TEXT("MRDIIFDI: Created empty DeviceInfoList\n"));
  191. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  192. if (SetupDiOpenDeviceInterface(hdi, DeviceInterface, 0,
  193. &DeviceInterfaceData))
  194. {
  195. SP_DEVINFO_DATA DeviceInfoData;
  196. DWORD cbDeviceInterfaceDetail;
  197. // dprintf(TEXT("MRDIIFDI: Opened DeviceInterface\n"));
  198. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  199. if (SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetail, &DeviceInfoData) ||
  200. (ERROR_INSUFFICIENT_BUFFER == GetLastError()))
  201. {
  202. DWORD cchDeviceInstanceId;
  203. // dprintf(TEXT("MRDIIFDI: Got DeviceInfoData\n"));
  204. if (SetupDiGetDeviceInstanceId(hdi, &DeviceInfoData, NULL, 0, &cchDeviceInstanceId) ||
  205. ERROR_INSUFFICIENT_BUFFER == GetLastError())
  206. {
  207. // dprintf(TEXT("MRDIIFDI: DeviceInstanceId is %d characters\n"), cchDeviceInstanceId);
  208. DeviceInstanceId = (PTSTR)HeapAlloc(hHeap, 0, cchDeviceInstanceId * sizeof(DeviceInstanceId[0]));
  209. if (DeviceInstanceId)
  210. {
  211. // dprintf(TEXT("MRDIIFDI: Allocated storage for DeviceInstanceId\n"));
  212. if (SetupDiGetDeviceInstanceId(hdi, &DeviceInfoData,
  213. DeviceInstanceId,
  214. cchDeviceInstanceId, NULL))
  215. {
  216. // dprintf(TEXT("MRDIIFDI: DeviceInstanceId=%ls\n"), DeviceInstanceId);
  217. } else {
  218. BOOL f;
  219. dwLastError = GetLastError();
  220. dprintf(TEXT("MRDIIFDI: Couldn't query DeviceInstanceId, LastError=%d\n"), dwLastError);
  221. f = HeapFree(hHeap, 0, DeviceInstanceId);
  222. DeviceInstanceId = NULL;
  223. ASSERT(f);
  224. }
  225. } else {
  226. dprintf(TEXT("MRDIIFDI: Could not allocate storage for DeviceInstanceId\n"));
  227. }
  228. } else {
  229. dwLastError = GetLastError();
  230. dprintf(TEXT("MRDIIFDI: Couldn't query size of DeviceInstanceId, LastError=%d\n"), dwLastError);
  231. }
  232. } else {
  233. dwLastError = GetLastError();
  234. dprintf(TEXT("MRDIIFDI: SetupDiGetDeviceInterfaceDetail failed LastError=%d\n"), dwLastError);
  235. }
  236. } else {
  237. dwLastError = GetLastError();
  238. dprintf(TEXT("MRDIIFDI: SetupDiOpenDeviceInterface failed, LastError=%d\n"), dwLastError);
  239. }
  240. if (!SetupDiDestroyDeviceInfoList(hdi))
  241. {
  242. dwLastError = GetLastError();
  243. dprintf(TEXT("MRDIIFDI: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError);
  244. }
  245. } else {
  246. dwLastError = GetLastError();
  247. dprintf(TEXT("MRDIIFDI: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError);
  248. }
  249. return DeviceInstanceId;
  250. }
  251. //--------------------------------------------------------------------------;
  252. //
  253. // MigrageNewDeviceInterfaceSetup
  254. //
  255. // Arguments:
  256. //
  257. // Return value:
  258. //
  259. // History:
  260. // 1/19/99 FrankYe Created
  261. //
  262. //--------------------------------------------------------------------------;
  263. void MigrateNewDeviceInterfaceSetup(PMMDEVICEINTERFACEINFO pdii, DWORD CurrentSetupCount)
  264. {
  265. HDEVINFO hdi;
  266. DWORD dwLastError;
  267. DWORD SetupCount;
  268. SetupCount = 0;
  269. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  270. if (INVALID_HANDLE_VALUE != hdi)
  271. {
  272. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  273. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  274. if (SetupDiOpenDeviceInterface(hdi, pdii->szName, 0, &DeviceInterfaceData))
  275. {
  276. HKEY hkeyDeviceInterface;
  277. hkeyDeviceInterface = SetupDiCreateDeviceInterfaceRegKeyW(hdi, &DeviceInterfaceData, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, NULL);
  278. if (INVALID_HANDLE_VALUE != hkeyDeviceInterface)
  279. {
  280. LONG result;
  281. result = RegQueryDwordValue(hkeyDeviceInterface, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount);
  282. if ((ERROR_SUCCESS != result) || (SetupCount < CurrentSetupCount))
  283. {
  284. SetupCount = CurrentSetupCount;
  285. if (ERROR_SUCCESS == RegSetDwordValue(hkeyDeviceInterface, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount))
  286. {
  287. // dprintf(TEXT("MNDIS: Success\n"));
  288. } else {
  289. dwLastError = GetLastError();
  290. dprintf(TEXT("MNDIS: RegSetValueEx failed, LastError=%d\n"), dwLastError);
  291. }
  292. }
  293. result = RegCloseKey(hkeyDeviceInterface);
  294. ASSERT(ERROR_SUCCESS == result);
  295. } else {
  296. dwLastError = GetLastError();
  297. dprintf(TEXT("MNDIS: SetupDiCreateDeviceInterfaceRegKey failed, LastError=%d\n"), dwLastError);
  298. }
  299. } else {
  300. dwLastError = GetLastError();
  301. dprintf(TEXT("MRDIIFDI: SetupDiOpenDeviceInterface failed, LastError=%d\n"), dwLastError);
  302. }
  303. if (!SetupDiDestroyDeviceInfoList(hdi))
  304. {
  305. dwLastError = GetLastError();
  306. dprintf(TEXT("MRDIIFDI: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError);
  307. }
  308. } else {
  309. dwLastError = GetLastError();
  310. dprintf(TEXT("MRDIIFDI: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError);
  311. }
  312. pdii->SetupPreferredAudioCount = SetupCount;
  313. return;
  314. }
  315. //--------------------------------------------------------------------------;
  316. //
  317. // MigrateNewDeviceInstanceSetup
  318. //
  319. // Arguments:
  320. //
  321. // Return value:
  322. //
  323. // History:
  324. // 11/9/98 FrankYe Created
  325. //
  326. //--------------------------------------------------------------------------;
  327. void MigrateNewDeviceInstanceSetup(PTSTR DeviceInstanceId, PDWORD pSetupCountOut)
  328. {
  329. HDEVINFO hdi;
  330. DWORD dwLastError;
  331. *pSetupCountOut = 0;
  332. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  333. if (INVALID_HANDLE_VALUE != hdi)
  334. {
  335. SP_DEVINFO_DATA DeviceInfoData;
  336. // dprintf(TEXT("MNDS: Created empty DeviceInfoList\n"));
  337. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  338. if (SetupDiOpenDeviceInfoW(hdi, DeviceInstanceId, NULL, 0, &DeviceInfoData))
  339. {
  340. HKEY hkeyDriver;
  341. hkeyDriver = SetupDiOpenDevRegKey(hdi, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE | KEY_SET_VALUE);
  342. if (INVALID_HANDLE_VALUE != hkeyDriver) {
  343. HKEY hkeyMmeDrivers;
  344. dwLastError = RegOpenKeyEx(hkeyDriver, TEXT("Drivers"), 0, KEY_QUERY_VALUE, &hkeyMmeDrivers);
  345. if (ERROR_SUCCESS == dwLastError)
  346. {
  347. DWORD fNewInstall;
  348. BOOL fSetupPreferredAudioDevices;
  349. DWORD cbfSetupPreferredAudioDevices;
  350. DWORD SetupCount;
  351. // Read the driver's existing setup count. If it doesn't exist
  352. // then this is a new install.
  353. dwLastError = RegQueryDwordValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount);
  354. if (ERROR_SUCCESS == dwLastError) {
  355. fNewInstall = FALSE;
  356. } else if (ERROR_FILE_NOT_FOUND == dwLastError) {
  357. fNewInstall = TRUE;
  358. SetupCount = 0;
  359. dwLastError = ERROR_SUCCESS;
  360. } else {
  361. fNewInstall = FALSE;
  362. SetupCount = 0;
  363. }
  364. if (ERROR_SUCCESS == dwLastError)
  365. {
  366. // Read the driver's SetupPreferredAudioDevices flag.
  367. cbfSetupPreferredAudioDevices = sizeof(fSetupPreferredAudioDevices);
  368. dwLastError = RegQueryValueEx(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICES, NULL, NULL, (PBYTE)&fSetupPreferredAudioDevices, &cbfSetupPreferredAudioDevices);
  369. if (ERROR_FILE_NOT_FOUND == dwLastError) {
  370. fSetupPreferredAudioDevices = FALSE;
  371. dwLastError = ERROR_SUCCESS;
  372. }
  373. // If this is a new install AND the driver .inf set the
  374. // fSetupPreferredAudioDevices flag, then let's try to
  375. // increment the machine setupcount and write the driver
  376. // setupcount.
  377. if ((ERROR_SUCCESS == dwLastError) && fNewInstall && fSetupPreferredAudioDevices)
  378. {
  379. HKEY hkeySetupPreferredAudioDevices;
  380. dwLastError = RegCreateKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES TEXT("\\") REGSTR_VAL_SETUPPREFERREDAUDIODEVICES, &hkeySetupPreferredAudioDevices);
  381. if (ERROR_SUCCESS == dwLastError)
  382. {
  383. dwLastError = RegQueryDwordValue(hkeySetupPreferredAudioDevices, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount);
  384. if (ERROR_FILE_NOT_FOUND == dwLastError) {
  385. SetupCount = 0;
  386. dwLastError = ERROR_SUCCESS;
  387. }
  388. if (ERROR_SUCCESS == dwLastError)
  389. {
  390. SetupCount++;
  391. dwLastError = RegSetDwordValue(hkeySetupPreferredAudioDevices, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount);
  392. if (ERROR_SUCCESS != dwLastError) dprintf(TEXT("MNDIS: Couldn't set count\n"));
  393. }
  394. RegCloseKey(hkeySetupPreferredAudioDevices);
  395. } else {
  396. dprintf(TEXT("MNDIS: Couldn't create hklm\\...\\SetupPreferredAudioDevices\n"));
  397. }
  398. }
  399. if (ERROR_SUCCESS == dwLastError) {
  400. // We've successfully read, incremented, and written the
  401. // setup version to HKLM, or we've done nothing because we
  402. // didn't have to.
  403. if (fNewInstall) RegSetDwordValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount);
  404. if (fSetupPreferredAudioDevices) RegDeleteValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICES);
  405. }
  406. }
  407. // Return the SetupCount for the driver
  408. *pSetupCountOut = SetupCount;
  409. RegCloseKey(hkeyMmeDrivers);
  410. }
  411. RegCloseKey(hkeyDriver);
  412. } else {
  413. dwLastError = GetLastError();
  414. dprintf(TEXT("MNDS: SetupDiCreateDevRegKey failed, LastError=%d\n"), dwLastError);
  415. }
  416. } else {
  417. dwLastError = GetLastError();
  418. dprintf(TEXT("MNDS: SetupDiOpenDeviceInfo failed, LastError=%d\n"), dwLastError);
  419. }
  420. if (!SetupDiDestroyDeviceInfoList(hdi))
  421. {
  422. dwLastError = GetLastError();
  423. dprintf(TEXT("MNDS: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError);
  424. }
  425. } else {
  426. dwLastError = GetLastError();
  427. dprintf(TEXT("MNDS: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError);
  428. }
  429. return;
  430. }
  431. //------------------------------------------------------------------------------
  432. //
  433. //
  434. // MigrateAutoSetupPreferredAudio
  435. //
  436. //
  437. //------------------------------------------------------------------------------
  438. void MigrateAutoSetupPreferredAudio(PMMDEVICEINTERFACEINFO pdii)
  439. {
  440. PTSTR pstrRendererDeviceInstanceId;
  441. DWORD SetupCount;
  442. SetupCount = 0;
  443. pstrRendererDeviceInstanceId = MakeRendererDeviceInstanceIdFromDeviceInterface(pdii->szName);
  444. if (pstrRendererDeviceInstanceId) {
  445. BOOL f;
  446. MigrateNewDeviceInstanceSetup(pstrRendererDeviceInstanceId, &SetupCount);
  447. f = HeapFree(hHeap, 0, pstrRendererDeviceInstanceId);
  448. ASSERT(f);
  449. }
  450. MigrateNewDeviceInterfaceSetup(pdii, SetupCount);
  451. return;
  452. }
  453. PMMDEVICEINTERFACEINFO pnpServerInstallDevice
  454. (
  455. PCTSTR pszDeviceInterface,
  456. BOOL fRemove
  457. )
  458. {
  459. PMMDEVICEINTERFACEINFO pdii;
  460. PWSTR pszDev;
  461. UINT ii;
  462. if (NULL == pPnpInfo)
  463. {
  464. dprintf(TEXT("pnpServerInstallDevice called at bad time\n"));
  465. ASSERT(FALSE);
  466. return NULL;
  467. }
  468. pdii = (PMMDEVICEINTERFACEINFO)&(pPnpInfo[1]);
  469. pdii = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdii);
  470. for (ii = pPnpInfo->cDevInterfaces; ii; ii--)
  471. {
  472. // Searching for the device interface...
  473. pszDev = (PWSTR)(&(pdii->szName[0]));
  474. if (0 == lstrcmpi(pszDev, pszDeviceInterface))
  475. {
  476. break;
  477. }
  478. pdii = (PMMDEVICEINTERFACEINFO)(pszDev + lstrlenW(pszDev) + 1);
  479. pdii = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdii);
  480. }
  481. // Getting the current settings...
  482. if (0 == ii)
  483. {
  484. PMMDEVICEINTERFACEINFO pdiiNext;
  485. SIZE_T sizePnpInfo;
  486. // Does not exist, create it, first ensuring there is enough room
  487. pdiiNext = (PMMDEVICEINTERFACEINFO)(pdii->szName + ((lstrlenW(pszDeviceInterface) + 1)));
  488. pdiiNext = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdiiNext);
  489. sizePnpInfo = ((PBYTE)pdiiNext) - ((PBYTE)pPnpInfo);
  490. if (sizePnpInfo < PNPINFOSIZE)
  491. {
  492. // dprintf(TEXT("pnpServerInstallDevice: note: sizePnpInfo = %p\n", sizePnpInfo);
  493. pdii->cPnpEvents = 0;
  494. pdii->fdwInfo = 0L;
  495. pszDev = (PWSTR)(&(pdii->szName[0]));
  496. lstrcpy(pszDev, pszDeviceInterface);
  497. pPnpInfo->cDevInterfaces++;
  498. pPnpInfo->cbSize = (DWORD)sizePnpInfo;
  499. } else {
  500. dprintf(TEXT("pnpServerInstallDevice RAN OUT OF PNPINO STORAGE!!!\n"));
  501. pdii = NULL;
  502. }
  503. }
  504. else
  505. {
  506. // Already exists, increment the event count.
  507. pdii->cPnpEvents++;
  508. }
  509. // Set or clear the "removed" bit.
  510. if (pdii)
  511. {
  512. if (fRemove)
  513. {
  514. pdii->fdwInfo |= MMDEVICEINFO_REMOVED;
  515. // dprintf("pnpServerInstallDevice removed [%ls]\n", pszDeviceInterface);
  516. }
  517. else
  518. {
  519. pdii->fdwInfo &= (~MMDEVICEINFO_REMOVED);
  520. // dprintf("pnpServerInstallDevice added [%ls]\n", pszDeviceInterface);
  521. }
  522. }
  523. return pdii;
  524. }
  525. BOOL PnpInfoEnum
  526. (
  527. void
  528. )
  529. {
  530. UINT cDevs = 0;
  531. HDEVINFO hDevInfo;
  532. BOOL fEnum;
  533. DWORD ii, dw;
  534. DWORD cbSize;
  535. GUID guidClass = KSCATEGORY_AUDIO;
  536. SP_DEVICE_INTERFACE_DATA did;
  537. SP_DEVINFO_DATA DevInfoData;
  538. PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd;
  539. cbSize = 300 * sizeof(TCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  540. pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(hHeap, 0, cbSize);
  541. if (NULL == pdidd)
  542. {
  543. HeapFree(hHeap, 0, pdidd);
  544. return FALSE;
  545. }
  546. pdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  547. hDevInfo = SetupDiGetClassDevs(
  548. &guidClass,
  549. NULL,
  550. NULL,
  551. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  552. if (INVALID_HANDLE_VALUE == hDevInfo)
  553. {
  554. dprintf(TEXT("SetupDiGetClasDevs failed [0x%08lx].\n"), GetLastError());
  555. HeapFree(hHeap, 0, pdidd);
  556. return FALSE;
  557. }
  558. ZeroMemory(&did, sizeof(did));
  559. did.cbSize = sizeof(did);
  560. ZeroMemory(&DevInfoData, sizeof(SP_DEVINFO_DATA));
  561. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  562. DevInfoData.ClassGuid = KSCATEGORY_AUDIO;
  563. for (ii = 0; ;ii++, cDevs++)
  564. {
  565. PMMDEVICEINTERFACEINFO pdii;
  566. fEnum = SetupDiEnumDeviceInterfaces(
  567. hDevInfo,
  568. NULL,
  569. &guidClass,
  570. ii,
  571. &did);
  572. if (!fEnum)
  573. {
  574. break;
  575. }
  576. dw = 0;
  577. fEnum = SetupDiGetDeviceInterfaceDetail(
  578. hDevInfo,
  579. &did,
  580. pdidd,
  581. cbSize,
  582. &dw,
  583. &DevInfoData);
  584. if (!fEnum)
  585. {
  586. dprintf(TEXT("SetupDiGetDeviceInterfaceDetail failed (0x%08lx).\n"), GetLastError());
  587. break;
  588. }
  589. // dprintf(TEXT("PnpInfoEnum: Enumerated[%ls]\n"), pdidd->DevicePath);
  590. pdii = pnpServerInstallDevice(pdidd->DevicePath, FALSE);
  591. if (pdii) MigrateAutoSetupPreferredAudio(pdii);
  592. }
  593. if (!SetupDiDestroyDeviceInfoList(hDevInfo))
  594. {
  595. ASSERT(!"wdmEnumerateInstalledDevices: SetupDiDestroyDeviceInfoList failed.");
  596. }
  597. HeapFree(hHeap, 0, pdidd);
  598. SetLastError(ERROR_SUCCESS);
  599. return TRUE;
  600. } // PnpInfoEnum()
  601. BOOL InitializePnpInfo
  602. (
  603. void
  604. )
  605. {
  606. SECURITY_ATTRIBUTES sa;
  607. PSECURITY_DESCRIPTOR pSd;
  608. BOOL result;
  609. ASSERT(!gfPnpInfoResource);
  610. ASSERT(!hPnpInfo);
  611. ASSERT(!pPnpInfo);
  612. result = FALSE;
  613. __try {
  614. RtlInitializeResource(&PnpInfoResource);
  615. gfPnpInfoResource = TRUE;
  616. } __except(EXCEPTION_EXECUTE_HANDLER) {
  617. gfPnpInfoResource = FALSE;;
  618. }
  619. if (!gfPnpInfoResource) return FALSE;
  620. pSd = BuildSecurityDescriptor(FILE_MAP_READ);
  621. if (pSd)
  622. {
  623. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  624. sa.lpSecurityDescriptor = pSd;
  625. sa.bInheritHandle = FALSE;
  626. hPnpInfo = CreateFileMapping(GetCurrentProcess(), &sa, PAGE_READWRITE, 0, PNPINFOSIZE, MMGLOBALPNPINFONAME);
  627. DestroySecurityDescriptor(pSd);
  628. if (hPnpInfo)
  629. {
  630. pPnpInfo = (PMMPNPINFO)MapViewOfFile(hPnpInfo, FILE_MAP_WRITE, 0, 0, 0);
  631. if (pPnpInfo)
  632. {
  633. ZeroMemory(pPnpInfo, PNPINFOSIZE);
  634. pPnpInfo->cbSize = sizeof(MMPNPINFO);
  635. pPnpInfo->cPnpEvents = 0;
  636. result = TRUE;
  637. } else {
  638. dprintf(TEXT("InitializePnpInfo: MapViewOfFile failed!\n"));
  639. }
  640. } else {
  641. dprintf(TEXT("InitializePnpInfo: CreateFileMappingFailed!\n"));
  642. }
  643. } else {
  644. dprintf(TEXT("InitializePnpInfo: BuildSecurityDescriptor failed!\n"));
  645. }
  646. if (!result)
  647. {
  648. if (pPnpInfo) UnmapViewOfFile(pPnpInfo);
  649. if (hPnpInfo) CloseHandle(hPnpInfo);
  650. if (gfPnpInfoResource) RtlDeleteResource(&PnpInfoResource);
  651. pPnpInfo = NULL;
  652. hPnpInfo = NULL;
  653. gfPnpInfoResource = FALSE;
  654. }
  655. return result;
  656. } // InitializePnpInfo()
  657. void DeletePnpInfo(void)
  658. {
  659. ASSERT(gfPnpInfoResource);
  660. ASSERT(hPnpInfo);
  661. ASSERT(pPnpInfo);
  662. UnmapViewOfFile(pPnpInfo);
  663. CloseHandle(hPnpInfo);
  664. RtlDeleteResource(&PnpInfoResource);
  665. pPnpInfo = NULL;
  666. hPnpInfo = NULL;
  667. gfPnpInfoResource = FALSE;
  668. return;
  669. }
  670. //=============================================================================
  671. //=== rpc functions ===
  672. //=============================================================================
  673. long s_wdmDriverOpenDrvRegKey(IN DWORD dwProcessId, IN LPCTSTR DeviceInterface, IN ULONG samDesired, OUT RHANDLE *phkeyClient)
  674. {
  675. HDEVINFO hdi;
  676. HKEY hkey;
  677. RPC_STATUS status;
  678. // We impersonate the client while calling setupapi so that we are sure
  679. // the client actually has access to open the driver reg key
  680. status = RpcImpersonateClient(NULL);
  681. if (status) return status;
  682. hdi = SetupDiCreateDeviceInfoList(NULL, NULL);
  683. if (INVALID_HANDLE_VALUE != hdi)
  684. {
  685. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  686. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  687. if (SetupDiOpenDeviceInterface(hdi, DeviceInterface, 0,
  688. &DeviceInterfaceData))
  689. {
  690. SP_DEVINFO_DATA DeviceInfoData;
  691. DWORD cbDeviceInterfaceDetail;
  692. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  693. if (SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetail, &DeviceInfoData) ||
  694. (ERROR_INSUFFICIENT_BUFFER == GetLastError()))
  695. {
  696. hkey = SetupDiOpenDevRegKey(hdi, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, samDesired);
  697. if (INVALID_HANDLE_VALUE != hkey)
  698. {
  699. status = ERROR_SUCCESS;
  700. } else {
  701. status = GetLastError();
  702. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiOpenDevRegKey failed, Error=%d\n"), status);
  703. }
  704. } else {
  705. status = GetLastError();
  706. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiGetDeviceInterfaceDetail failed, Error=%d\n"), status);
  707. }
  708. } else {
  709. status = GetLastError();
  710. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiOpenDeviceInterface failed, Error=%d\n"), status);
  711. }
  712. SetupDiDestroyDeviceInfoList(hdi);
  713. } else {
  714. status = GetLastError();
  715. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiCreateDeviceInfoList failed, Error=%d\n"), status);
  716. }
  717. // We stop impersonating here because the remaining operations
  718. // should not depend on the client's privileges.
  719. RpcRevertToSelf();
  720. if (ERROR_SUCCESS == status)
  721. {
  722. HANDLE hClientProcess;
  723. hClientProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  724. if (hClientProcess)
  725. {
  726. HANDLE hkeyClient;
  727. if (DuplicateHandle(GetCurrentProcess(), hkey, hClientProcess, &hkeyClient, 0, FALSE, DUPLICATE_SAME_ACCESS))
  728. {
  729. // dprintf(TEXT("s_wdmDriverOpenDrvRegKey hkeyClient=%p\n"), hkeyClient);
  730. *phkeyClient = (RHANDLE)hkeyClient;
  731. } else {
  732. status = GetLastError();
  733. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: DuplicateHandle failed, Error=%d\n"), status);
  734. }
  735. CloseHandle(hClientProcess);
  736. } else {
  737. status = GetLastError();
  738. dprintf(TEXT("s_wdmDriverOpenDrvRegKey: OpenProcess failed, Error=%d\n"), status);
  739. }
  740. RegCloseKey(hkey);
  741. }
  742. return status;
  743. }
  744. void s_winmmAdvisePreferredDeviceChange(void)
  745. {
  746. // dprintf(TEXT("s_winmmAdvisePreferredDeviceChange\n"));
  747. ASSERT(pPnpInfo);
  748. InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges);
  749. BroadcastWinmmDeviceChange();
  750. return;
  751. }
  752. long s_winmmGetPnpInfo(OUT LONG *pcbPnpInfo, OUT BYTE **ppPnpInfoOut)
  753. {
  754. static BOOL fEnumDone = FALSE;
  755. PBYTE pPnpInfoOut;
  756. LONG result;
  757. // dprintf(TEXT("s_winmmGetPnpInfo\n"));
  758. ASSERT(pPnpInfo);
  759. RtlAcquireResourceShared(&PnpInfoResource, TRUE);
  760. pPnpInfoOut = (PBYTE)HeapAlloc(hHeap, 0, pPnpInfo->cbSize);
  761. if (pPnpInfoOut)
  762. {
  763. CopyMemory(pPnpInfoOut, pPnpInfo, pPnpInfo->cbSize);
  764. *pcbPnpInfo = pPnpInfo->cbSize;
  765. *ppPnpInfoOut = pPnpInfoOut;
  766. result = NO_ERROR;
  767. } else {
  768. // ISSUE-2001/02/15-FrankYe Do we need to zero the out params?
  769. result = ERROR_OUTOFMEMORY;
  770. }
  771. RtlReleaseResource(&PnpInfoResource);
  772. return result;
  773. }
  774. //=============================================================================
  775. //=== pnp interface handlers ===
  776. //=============================================================================
  777. void MME_AudioInterfaceArrival(PCTSTR DeviceInterface)
  778. {
  779. PMMDEVICEINTERFACEINFO pdii;
  780. // dprintf(TEXT("MME_AudioInterfaceArrival\n"));
  781. RtlAcquireResourceExclusive(&PnpInfoResource, TRUE);
  782. pdii = pnpServerInstallDevice(DeviceInterface, FALSE);
  783. if (pdii) MigrateAutoSetupPreferredAudio(pdii);
  784. InterlockedIncrement(&pPnpInfo->cPnpEvents);
  785. InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges);
  786. RtlReleaseResource(&PnpInfoResource);
  787. if (pdii) BroadcastWinmmDeviceChange();
  788. return;
  789. }
  790. void MME_AudioInterfaceRemove(PCTSTR DeviceInterface)
  791. {
  792. PMMDEVICEINTERFACEINFO pdii;
  793. // dprintf(TEXT("MME_AudioInterfaceRemove\n"));
  794. RtlAcquireResourceExclusive(&PnpInfoResource, TRUE);
  795. pdii = pnpServerInstallDevice(DeviceInterface, TRUE);
  796. InterlockedIncrement(&pPnpInfo->cPnpEvents);
  797. InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges);
  798. RtlReleaseResource(&PnpInfoResource);
  799. if (pdii) BroadcastWinmmDeviceChange();
  800. return;
  801. }
  802. LONG MME_ServiceStart(void)
  803. {
  804. ASSERT(pPnpInfo);
  805. // dprintf(TEXT("MME_ServiceStart\n"));
  806. RtlAcquireResourceExclusive(&PnpInfoResource, TRUE);
  807. if (!PnpInfoEnum()) dprintf(TEXT("MME_ServiceStart: PnpInfoEnum failed!\n"));
  808. InterlockedIncrement(&pPnpInfo->cPnpEvents);
  809. RtlReleaseResource(&PnpInfoResource);
  810. return NO_ERROR;
  811. }
  812. //=============================================================================
  813. //=== DLL attach/detach ===
  814. //=============================================================================
  815. BOOL MME_DllProcessAttach(void)
  816. {
  817. return InitializePnpInfo();
  818. }
  819. void MME_DllProcessDetach(void)
  820. {
  821. return DeletePnpInfo();
  822. }