Source code of Windows XP (NT5)
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.

723 lines
25 KiB

  1. /****************************************************************************
  2. *
  3. * File: sndinfo.cpp
  4. * Project: DxDiag (DirectX Diagnostic Tool)
  5. * Author: Mike Anderson (manders@microsoft.com)
  6. * Purpose: Gather information about sound devices on this machine
  7. *
  8. * (C) Copyright 1998-1999 Microsoft Corp. All rights reserved.
  9. *
  10. ****************************************************************************/
  11. #define DIRECTSOUND_VERSION 0x0600
  12. #include <tchar.h>
  13. #include <Windows.h>
  14. #include <mmsystem.h>
  15. #include <d3dtypes.h>
  16. #include <dsound.h>
  17. #include <stdio.h>
  18. #include "mmddk.h" // for DRV_QUERYDEVNODE
  19. #include "dsprv.h"
  20. #include "dsprvobj.h"
  21. #include "reginfo.h"
  22. #include "sysinfo.h" // for BIsPlatformNT
  23. #include "dispinfo.h"
  24. #include "sndinfo.h"
  25. #include "fileinfo.h" // for GetFileVersion, FileIsSigned
  26. #include "resource.h"
  27. // This function is defined in sndinfo7.cpp:
  28. HRESULT GetRegKey(LPKSPROPERTYSET pKSPS7, REFGUID guidDeviceID, TCHAR* pszRegKey);
  29. typedef HRESULT (WINAPI* LPDIRECTSOUNDENUMERATE)(LPDSENUMCALLBACK lpDSEnumCallback,
  30. LPVOID lpContext);
  31. typedef HRESULT (WINAPI* LPDIRECTSOUNDCREATE)(LPGUID lpGUID, LPDIRECTSOUND* ppDS,
  32. LPUNKNOWN pUnkOuter);
  33. static BOOL CALLBACK DSEnumCallback(LPGUID pGuid, TCHAR* pszDescription,
  34. TCHAR* pszModule, LPVOID lpContext);
  35. static VOID GetRegSoundInfo9x(SoundInfo* pSoundInfo);
  36. static VOID GetRegSoundInfoNT(SoundInfo* pSoundInfo);
  37. static HRESULT GetDirectSoundInfo(LPDIRECTSOUNDCREATE pDSCreate, SoundInfo* pSoundInfo);
  38. static HRESULT CheckRegistry(RegError** ppRegErrorFirst);
  39. static LPKSPROPERTYSET s_pKSPS = NULL;
  40. static DWORD s_dwWaveIDDefault = 0;
  41. /****************************************************************************
  42. *
  43. * GetBasicSoundInfo
  44. *
  45. ****************************************************************************/
  46. HRESULT GetBasicSoundInfo(SoundInfo** ppSoundInfoFirst)
  47. {
  48. HRESULT hr = S_OK;
  49. TCHAR szPath[MAX_PATH];
  50. HINSTANCE hInstDSound = NULL;
  51. LPDIRECTSOUNDENUMERATE pdse;
  52. lstrcpy( szPath, TEXT("") );
  53. // Find which waveout device is the default, the one that would
  54. // be used by DirectSoundCreate(NULL). If the following code
  55. // fails, assume it's device 0.
  56. DWORD dwParam2 = 0;
  57. waveOutMessage( (HWAVEOUT)IntToPtr(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &s_dwWaveIDDefault, (DWORD_PTR) &dwParam2 );
  58. if( s_dwWaveIDDefault == -1 )
  59. s_dwWaveIDDefault = 0;
  60. GetSystemDirectory(szPath, MAX_PATH);
  61. lstrcat(szPath, TEXT("\\dsound.dll"));
  62. hInstDSound = LoadLibrary(szPath);
  63. if (hInstDSound == NULL)
  64. goto LEnd;
  65. // Get Private DirectSound object:
  66. if (FAILED(hr = DirectSoundPrivateCreate(&s_pKSPS)))
  67. {
  68. // note: no error. This will always fail on Win95.
  69. }
  70. // Get DirectSoundEnumerate and call it:
  71. pdse = (LPDIRECTSOUNDENUMERATE)GetProcAddress(hInstDSound,
  72. #ifdef UNICODE
  73. "DirectSoundEnumerateW"
  74. #else
  75. "DirectSoundEnumerateA"
  76. #endif
  77. );
  78. if (pdse == NULL)
  79. goto LEnd;
  80. if (FAILED(hr = pdse((LPDSENUMCALLBACK)DSEnumCallback, ppSoundInfoFirst)))
  81. goto LEnd;
  82. LEnd:
  83. if (s_pKSPS != NULL)
  84. {
  85. s_pKSPS->Release();
  86. s_pKSPS = NULL;
  87. }
  88. if (hInstDSound != NULL)
  89. FreeLibrary(hInstDSound);
  90. return hr;
  91. }
  92. /****************************************************************************
  93. *
  94. * DSEnumCallback
  95. *
  96. ****************************************************************************/
  97. BOOL CALLBACK DSEnumCallback(LPGUID pGuid, TCHAR* pszDescription,
  98. TCHAR* pszModule, LPVOID lpContext)
  99. {
  100. SoundInfo** ppSoundInfoFirst = (SoundInfo**)lpContext;
  101. SoundInfo* pSoundInfoNew;
  102. PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pdsdData = NULL;
  103. if (pGuid == NULL)
  104. return TRUE; // skip this guy
  105. // We decided to only report on the default, primary DSound device for
  106. // now. Remove the next few lines to show a page per device.
  107. // Use private interface to get bonus information:
  108. if (*ppSoundInfoFirst != NULL)
  109. return FALSE; // We got our device, so stop enumerating
  110. if (s_pKSPS != NULL)
  111. {
  112. if (FAILED(PrvGetDeviceDescription(s_pKSPS, *pGuid, &pdsdData)))
  113. return TRUE; // error on this device--keep enumerating
  114. if (pdsdData->WaveDeviceId != s_dwWaveIDDefault)
  115. return TRUE; // not default device--keep enumerating
  116. }
  117. // Note: on Win95, where s_pKSPS is NULL, we can't get the device ID,
  118. // so we don't know which DSound device is the default one. So just
  119. // use the first one that comes up in the enumeration after the one
  120. // with NULL pGuid.
  121. pSoundInfoNew = new SoundInfo;
  122. if (pSoundInfoNew == NULL)
  123. return FALSE;
  124. ZeroMemory(pSoundInfoNew, sizeof(SoundInfo));
  125. if (*ppSoundInfoFirst == NULL)
  126. {
  127. *ppSoundInfoFirst = pSoundInfoNew;
  128. }
  129. else
  130. {
  131. SoundInfo* pSoundInfo;
  132. for (pSoundInfo = *ppSoundInfoFirst;
  133. pSoundInfo->m_pSoundInfoNext != NULL;
  134. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  135. {
  136. }
  137. pSoundInfo->m_pSoundInfoNext = pSoundInfoNew;
  138. }
  139. pSoundInfoNew->m_guid = *pGuid;
  140. lstrcpy(pSoundInfoNew->m_szDescription, pszDescription);
  141. if (s_pKSPS == NULL)
  142. {
  143. // Without the DSound private interface, we can't use it to get
  144. // waveout device ID or devnode. Assume device ID is 0, and use
  145. // waveOutMessage(DRV_QUERYDEVNODE) to get dev node.
  146. waveOutMessage((HWAVEOUT)0, DRV_QUERYDEVNODE, (DWORD_PTR)&pSoundInfoNew->m_dwDevnode, 0);
  147. pSoundInfoNew->m_lwAccelerationLevel = -1;
  148. }
  149. else
  150. {
  151. pSoundInfoNew->m_dwDevnode = pdsdData->Devnode;
  152. if (pdsdData->Type == 0)
  153. LoadString(NULL, IDS_EMULATED, pSoundInfoNew->m_szType, 100);
  154. else if (pdsdData->Type == 1)
  155. LoadString(NULL, IDS_VXD, pSoundInfoNew->m_szType, 100);
  156. else if (pdsdData->Type == 2)
  157. LoadString(NULL, IDS_WDM, pSoundInfoNew->m_szType, 100);
  158. DIRECTSOUNDBASICACCELERATION_LEVEL accelLevel;
  159. if (FAILED(PrvGetBasicAcceleration(s_pKSPS, *pGuid, &accelLevel)))
  160. pSoundInfoNew->m_lwAccelerationLevel = -1;
  161. else
  162. pSoundInfoNew->m_lwAccelerationLevel = (LONG)accelLevel;
  163. // This will only work on DX7 and beyond
  164. GetRegKey(s_pKSPS, *pGuid, pSoundInfoNew->m_szRegKey);
  165. }
  166. WAVEOUTCAPS waveoutcaps;
  167. LONG devID;
  168. if (pdsdData == NULL)
  169. devID = 0;
  170. else
  171. devID = pdsdData->WaveDeviceId;
  172. if (MMSYSERR_NOERROR == waveOutGetDevCaps(devID, &waveoutcaps, sizeof(waveoutcaps)))
  173. {
  174. // May want to use mmreg.h to add strings for manufacturer/product names here
  175. wsprintf(pSoundInfoNew->m_szManufacturerID, TEXT("%d"), waveoutcaps.wMid);
  176. wsprintf(pSoundInfoNew->m_szProductID, TEXT("%d"), waveoutcaps.wPid);
  177. }
  178. // Sometimes, pszModule is the full path. Sometimes it's just the leaf.
  179. // Sometimes, it's something inbetween. Separate the leaf, and look
  180. // in a few different places.
  181. TCHAR* pszLeaf;
  182. pszLeaf = _tcsrchr(pszModule, TEXT('\\'));
  183. if (pszLeaf == NULL)
  184. {
  185. lstrcpy(pSoundInfoNew->m_szDriverName, pszModule);
  186. }
  187. else
  188. {
  189. lstrcpy(pSoundInfoNew->m_szDriverName, (pszLeaf + 1));
  190. }
  191. // Try just module string
  192. lstrcpy(pSoundInfoNew->m_szDriverPath, pszModule);
  193. if (pszLeaf == NULL || GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  194. {
  195. // Try windows dir + module string
  196. GetWindowsDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH);
  197. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\"));
  198. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  199. if (GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  200. {
  201. // Try system dir + module string
  202. GetSystemDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH);
  203. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\"));
  204. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  205. if (GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  206. {
  207. // Try windows dir + \system32\drivers\ + module string
  208. GetWindowsDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH);
  209. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\System32\\Drivers\\"));
  210. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  211. }
  212. }
  213. }
  214. PrvReleaseDeviceDescription( pdsdData );
  215. return TRUE;
  216. }
  217. /****************************************************************************
  218. *
  219. * GetExtraSoundInfo
  220. *
  221. ****************************************************************************/
  222. HRESULT GetExtraSoundInfo(SoundInfo* pSoundInfoFirst)
  223. {
  224. SoundInfo* pSoundInfo;
  225. BOOL bNT = BIsPlatformNT();
  226. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  227. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  228. {
  229. CheckRegistry(&pSoundInfo->m_pRegErrorFirst);
  230. if (bNT)
  231. GetRegSoundInfoNT(pSoundInfo);
  232. else
  233. GetRegSoundInfo9x(pSoundInfo);
  234. // Bug 18245: Try to distinguish between the various IBM MWave cards
  235. if (_tcsstr(pSoundInfo->m_szDeviceID, TEXT("MWAVEAUDIO_0460")) != NULL)
  236. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Stingray)"));
  237. else if (_tcsstr(pSoundInfo->m_szDeviceID, TEXT("MWAVEAUDIO_0465")) != NULL)
  238. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Marlin)"));
  239. else
  240. {
  241. TCHAR szBoard[100];
  242. lstrcpy( szBoard, TEXT("") );
  243. GetPrivateProfileString(TEXT("Mwave,Board"), TEXT("board"), TEXT(""),
  244. szBoard, 100, TEXT("MWave.ini"));
  245. if (lstrcmp(szBoard, TEXT("MWAT-046")) == 0)
  246. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Dolphin)"));
  247. else if (lstrcmp(szBoard, TEXT("MWAT-043")) == 0)
  248. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Whale)"));
  249. }
  250. // Sometimes, like when a sound driver is emulated, the driver
  251. // will be reported as something like "WaveOut 0". In this case,
  252. // just blank out the file-related fields.
  253. if (_tcsstr(pSoundInfo->m_szDriverName, TEXT(".")) == NULL)
  254. {
  255. lstrcpy(pSoundInfo->m_szDriverName, TEXT(""));
  256. lstrcpy(pSoundInfo->m_szDriverPath, TEXT(""));
  257. }
  258. else
  259. {
  260. GetFileVersion(pSoundInfo->m_szDriverPath, pSoundInfo->m_szDriverVersion,
  261. pSoundInfo->m_szDriverAttributes, pSoundInfo->m_szDriverLanguageLocal, pSoundInfo->m_szDriverLanguage,
  262. &pSoundInfo->m_bDriverBeta, &pSoundInfo->m_bDriverDebug);
  263. FileIsSigned(pSoundInfo->m_szDriverPath, &pSoundInfo->m_bDriverSigned, &pSoundInfo->m_bDriverSignedValid);
  264. GetFileDateAndSize(pSoundInfo->m_szDriverPath,
  265. pSoundInfo->m_szDriverDateLocal, pSoundInfo->m_szDriverDate, &pSoundInfo->m_numBytes);
  266. }
  267. }
  268. return S_OK;
  269. }
  270. /****************************************************************************
  271. *
  272. * GetRegSoundInfo9x
  273. *
  274. ****************************************************************************/
  275. VOID GetRegSoundInfo9x(SoundInfo* pSoundInfo)
  276. {
  277. HKEY hkey = NULL;
  278. DWORD iKey = 0;
  279. TCHAR szSubKey[200];
  280. DWORD dwSubKeySize;
  281. TCHAR szClass[100];
  282. DWORD dwClassSize;
  283. HKEY hkeySub = NULL;
  284. DWORD dwDevnode;
  285. DWORD cb;
  286. DWORD dwType;
  287. HKEY hkeyOther = NULL;
  288. // We have the DevNode, so find the device in the registry with the
  289. // matching DevNode and gather more info there.
  290. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\control\\MediaResources\\wave"),
  291. 0, KEY_READ, &hkey))
  292. {
  293. while (TRUE)
  294. {
  295. dwSubKeySize = sizeof(szSubKey);
  296. dwClassSize = sizeof(szClass);
  297. if (ERROR_SUCCESS != RegEnumKeyEx(hkey, iKey, szSubKey, &dwSubKeySize, NULL, szClass, &dwClassSize, NULL))
  298. break;
  299. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szSubKey, 0, KEY_READ, &hkeySub))
  300. {
  301. cb = sizeof(dwDevnode);
  302. if (ERROR_SUCCESS == RegQueryValueEx(hkeySub, TEXT("DevNode"), NULL, &dwType, (BYTE*)&dwDevnode, &cb))
  303. {
  304. if (dwDevnode == pSoundInfo->m_dwDevnode)
  305. {
  306. // Found match...gather yummy info
  307. cb = sizeof(pSoundInfo->m_szDeviceID);
  308. RegQueryValueEx(hkeySub, TEXT("DeviceID"), NULL, &dwType, (BYTE*)pSoundInfo->m_szDeviceID, &cb);
  309. // Occasionally the driver name that DirectSoundEnumerate spits out
  310. // is garbage (as with my Crystal SoundFusion). If that's the case,
  311. // use the driver name listed here instead.
  312. if (lstrlen(pSoundInfo->m_szDriverName) < 4)
  313. {
  314. cb = sizeof(pSoundInfo->m_szDriverName);
  315. RegQueryValueEx(hkeySub, TEXT("Driver"), NULL, &dwType, (BYTE*)pSoundInfo->m_szDriverName, &cb);
  316. GetSystemDirectory(pSoundInfo->m_szDriverPath, MAX_PATH);
  317. lstrcat(pSoundInfo->m_szDriverPath, TEXT("\\"));
  318. lstrcat(pSoundInfo->m_szDriverPath, pSoundInfo->m_szDriverName);
  319. }
  320. TCHAR szOtherKey[300];
  321. cb = sizeof(szOtherKey);
  322. RegQueryValueEx(hkeySub, TEXT("SOFTWAREKEY"), NULL, &dwType, (BYTE*)szOtherKey, &cb);
  323. if (lstrlen(szOtherKey) > 0)
  324. {
  325. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szOtherKey, 0, KEY_READ, &hkeyOther))
  326. {
  327. cb = sizeof(pSoundInfo->m_szOtherDrivers);
  328. RegQueryValueEx(hkeyOther, TEXT("Driver"), NULL, &dwType, (BYTE*)pSoundInfo->m_szOtherDrivers, &cb);
  329. cb = sizeof(pSoundInfo->m_szProvider);
  330. RegQueryValueEx(hkeyOther, TEXT("ProviderName"), NULL, &dwType, (BYTE*)pSoundInfo->m_szProvider, &cb);
  331. RegCloseKey(hkeyOther);
  332. }
  333. }
  334. }
  335. }
  336. RegCloseKey(hkeySub);
  337. }
  338. iKey++;
  339. }
  340. RegCloseKey(hkey);
  341. }
  342. }
  343. /****************************************************************************
  344. *
  345. * GetRegSoundInfoNT
  346. *
  347. ****************************************************************************/
  348. VOID GetRegSoundInfoNT(SoundInfo* pSoundInfo)
  349. {
  350. TCHAR szFullKey[200];
  351. HKEY hkey;
  352. DWORD cbData;
  353. DWORD dwType;
  354. TCHAR szDriverKey[200];
  355. TCHAR szOtherFullKey[200];
  356. lstrcpy(szFullKey, TEXT("System\\CurrentControlSet\\Enum\\"));
  357. lstrcat(szFullKey, pSoundInfo->m_szRegKey);
  358. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
  359. {
  360. cbData = sizeof(pSoundInfo->m_szDeviceID);
  361. RegQueryValueEx(hkey, TEXT("HardwareID"), 0, &dwType, (LPBYTE)pSoundInfo->m_szDeviceID, &cbData);
  362. cbData = sizeof(szDriverKey);
  363. RegQueryValueEx(hkey, TEXT("Driver"), 0, &dwType, (LPBYTE)szDriverKey, &cbData);
  364. RegCloseKey(hkey);
  365. }
  366. lstrcpy(szOtherFullKey, TEXT("System\\CurrentControlSet\\Control\\Class\\"));
  367. lstrcat(szOtherFullKey, szDriverKey);
  368. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szOtherFullKey, 0, KEY_READ, &hkey))
  369. {
  370. cbData = sizeof(pSoundInfo->m_szProvider);
  371. RegQueryValueEx(hkey, TEXT("ProviderName"), 0, &dwType, (LPBYTE)pSoundInfo->m_szProvider, &cbData);
  372. RegCloseKey(hkey);
  373. }
  374. }
  375. /****************************************************************************
  376. *
  377. * GetDSSoundInfo
  378. *
  379. ****************************************************************************/
  380. HRESULT GetDSSoundInfo(SoundInfo* pSoundInfoFirst)
  381. {
  382. HRESULT hr;
  383. HRESULT hrRet = S_OK;
  384. SoundInfo* pSoundInfo;
  385. TCHAR szPath[MAX_PATH];
  386. HINSTANCE hInstDSound;
  387. LPDIRECTSOUNDCREATE pDSCreate;
  388. GetSystemDirectory(szPath, MAX_PATH);
  389. lstrcat(szPath, TEXT("\\dsound.dll"));
  390. hInstDSound = LoadLibrary(szPath);
  391. if (hInstDSound == NULL)
  392. return E_FAIL;
  393. pDSCreate = (LPDIRECTSOUNDCREATE)GetProcAddress(hInstDSound, "DirectSoundCreate");
  394. if (pDSCreate == NULL)
  395. {
  396. FreeLibrary(hInstDSound);
  397. return E_FAIL;
  398. }
  399. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  400. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  401. {
  402. if (FAILED(hr = GetDirectSoundInfo(pDSCreate, pSoundInfo)))
  403. hrRet = hr; // but keep going
  404. }
  405. FreeLibrary(hInstDSound);
  406. return hrRet;
  407. }
  408. /****************************************************************************
  409. *
  410. * IsDriverWDM
  411. *
  412. ****************************************************************************/
  413. BOOL IsDriverWDM( TCHAR* szDriverName )
  414. {
  415. if( _tcsstr( szDriverName, TEXT(".sys") ) == NULL )
  416. return FALSE;
  417. else
  418. return TRUE;
  419. }
  420. /****************************************************************************
  421. *
  422. * GetDirectSoundInfo
  423. *
  424. ****************************************************************************/
  425. HRESULT GetDirectSoundInfo(LPDIRECTSOUNDCREATE pDSCreate, SoundInfo* pSoundInfo)
  426. {
  427. HRESULT hr;
  428. LPDIRECTSOUND pds = NULL;
  429. GUID* pGUID;
  430. DSCAPS dscaps;
  431. // Right now, this function only calls DSCreate/GetCaps to determine if
  432. // the driver is signed. If we have already determined that it is by
  433. // other means, don't bother with this test.
  434. if (pSoundInfo->m_bDriverSigned)
  435. return S_OK;
  436. // Bug 29918: If this is a WDM driver, then don't call GetCaps() since
  437. // on DX7.1+ GetCaps() will always return DSCAPS_CERTIFIED on WDM drivers
  438. if( IsDriverWDM( pSoundInfo->m_szDriverName ) )
  439. return S_OK;
  440. if (pSoundInfo->m_guid == GUID_NULL)
  441. pGUID = NULL;
  442. else
  443. pGUID = &pSoundInfo->m_guid;
  444. if (FAILED(hr = pDSCreate(pGUID, &pds, NULL)))
  445. goto LFail;
  446. dscaps.dwSize = sizeof(dscaps);
  447. if (FAILED(hr = pds->GetCaps(&dscaps)))
  448. goto LFail;
  449. pSoundInfo->m_bDriverSignedValid = TRUE;
  450. if (dscaps.dwFlags & DSCAPS_CERTIFIED)
  451. pSoundInfo->m_bDriverSigned = TRUE;
  452. pds->Release();
  453. return S_OK;
  454. LFail:
  455. if (pds != NULL)
  456. pds->Release();
  457. return hr;
  458. }
  459. /****************************************************************************
  460. *
  461. * ChangeAccelerationLevel
  462. *
  463. ****************************************************************************/
  464. HRESULT ChangeAccelerationLevel(SoundInfo* pSoundInfo, LONG lwLevel)
  465. {
  466. HRESULT hr = S_OK;
  467. DIRECTSOUNDBASICACCELERATION_LEVEL level = (DIRECTSOUNDBASICACCELERATION_LEVEL)lwLevel;
  468. LPKSPROPERTYSET pksps = NULL;
  469. TCHAR szPath[MAX_PATH];
  470. HINSTANCE hInstDSound = NULL;
  471. GetSystemDirectory(szPath, MAX_PATH);
  472. lstrcat(szPath, TEXT("\\dsound.dll"));
  473. hInstDSound = LoadLibrary(szPath);
  474. if (hInstDSound == NULL)
  475. {
  476. hr = DDERR_NOTFOUND;
  477. goto LEnd;
  478. }
  479. if (FAILED(hr = DirectSoundPrivateCreate(&pksps)))
  480. goto LEnd;
  481. if (FAILED(hr = PrvSetBasicAcceleration(pksps, pSoundInfo->m_guid, level)))
  482. goto LEnd;
  483. LEnd:
  484. if (pksps != NULL)
  485. pksps->Release();
  486. if (hInstDSound != NULL)
  487. FreeLibrary(hInstDSound);
  488. pSoundInfo->m_lwAccelerationLevel = lwLevel;
  489. return hr;
  490. }
  491. /****************************************************************************
  492. *
  493. * CheckRegistry
  494. *
  495. ****************************************************************************/
  496. HRESULT CheckRegistry(RegError** ppRegErrorFirst)
  497. {
  498. HRESULT hr;
  499. HKEY HKCR = HKEY_CLASSES_ROOT;
  500. TCHAR szVersion[100];
  501. HKEY hkey;
  502. DWORD cbData;
  503. ULONG ulType;
  504. DWORD dwMajor = 0;
  505. DWORD dwMinor = 0;
  506. DWORD dwRevision = 0;
  507. DWORD dwBuild = 0;
  508. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
  509. 0, KEY_READ, &hkey))
  510. {
  511. cbData = 100;
  512. RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)szVersion, &cbData);
  513. RegCloseKey(hkey);
  514. if (lstrlen(szVersion) > 6 &&
  515. lstrlen(szVersion) < 20)
  516. {
  517. _stscanf(szVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild);
  518. }
  519. }
  520. // No registry checking on DX versions before DX7
  521. if (dwMinor < 7)
  522. return S_OK;
  523. // From dsound.inf:
  524. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSound"), TEXT(""), TEXT("*"))))
  525. return hr;
  526. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSound\\CLSID"), TEXT(""), TEXT("{47D4D946-62E8-11cf-93BC-444553540000}"))))
  527. return hr;
  528. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}"), TEXT(""), TEXT("*"))))
  529. return hr;
  530. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}\\InprocServer32"), TEXT(""), TEXT("dsound.dll"), CRF_LEAF)))
  531. return hr;
  532. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  533. return hr;
  534. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSoundCapture"), TEXT(""), TEXT("*"))))
  535. return hr;
  536. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSoundCapture\\CLSID"), TEXT(""), TEXT("{B0210780-89CD-11d0-AF08-00A0C925CD16}"))))
  537. return hr;
  538. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}"), TEXT(""), TEXT("*"))))
  539. return hr;
  540. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}\\InprocServer32"), TEXT(""), TEXT("dsound.dll"), CRF_LEAF)))
  541. return hr;
  542. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  543. return hr;
  544. return S_OK;
  545. }
  546. /****************************************************************************
  547. *
  548. * DestroySoundInfo
  549. *
  550. ****************************************************************************/
  551. VOID DestroySoundInfo(SoundInfo* pSoundInfoFirst)
  552. {
  553. SoundInfo* pSoundInfo;
  554. SoundInfo* pSoundInfoNext;
  555. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  556. pSoundInfo = pSoundInfoNext)
  557. {
  558. DestroyReg( &pSoundInfo->m_pRegErrorFirst );
  559. pSoundInfoNext = pSoundInfo->m_pSoundInfoNext;
  560. delete pSoundInfo;
  561. }
  562. }
  563. /****************************************************************************
  564. *
  565. * DiagnoseSound
  566. *
  567. ****************************************************************************/
  568. VOID DiagnoseSound(SoundInfo* pSoundInfoFirst)
  569. {
  570. SoundInfo* pSoundInfo;
  571. TCHAR sz[500];
  572. TCHAR szFmt[500];
  573. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  574. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  575. {
  576. _tcscpy( pSoundInfo->m_szNotes, TEXT("") );
  577. _tcscpy( pSoundInfo->m_szNotesEnglish, TEXT("") );
  578. // Report any problems:
  579. BOOL bProblem = FALSE;
  580. if ( pSoundInfo->m_bDriverSignedValid &&
  581. !pSoundInfo->m_bDriverSigned &&
  582. lstrlen(pSoundInfo->m_szDriverName) > 0)
  583. {
  584. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1, szFmt, 300);
  585. wsprintf(sz, szFmt, pSoundInfo->m_szDriverName);
  586. _tcscat( pSoundInfo->m_szNotes, sz );
  587. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1_ENGLISH, szFmt, 300);
  588. wsprintf(sz, szFmt, pSoundInfo->m_szDriverName);
  589. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  590. bProblem = TRUE;
  591. }
  592. if (pSoundInfo->m_pRegErrorFirst != NULL)
  593. {
  594. LoadString(NULL, IDS_REGISTRYPROBLEM, sz, 500);
  595. _tcscat( pSoundInfo->m_szNotes, sz );
  596. LoadString(NULL, IDS_REGISTRYPROBLEM_ENGLISH, sz, 500);
  597. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  598. bProblem = TRUE;
  599. }
  600. // Report any DSound test results:
  601. if (pSoundInfo->m_testResultSnd.m_bStarted &&
  602. !pSoundInfo->m_testResultSnd.m_bCancelled)
  603. {
  604. LoadString(NULL, IDS_DSRESULTS, sz, 500);
  605. _tcscat( pSoundInfo->m_szNotes, sz );
  606. _tcscat( pSoundInfo->m_szNotes, pSoundInfo->m_testResultSnd.m_szDescription );
  607. _tcscat( pSoundInfo->m_szNotes, TEXT("\r\n") );
  608. LoadString(NULL, IDS_DSRESULTS_ENGLISH, sz, 500);
  609. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  610. _tcscat( pSoundInfo->m_szNotesEnglish, pSoundInfo->m_testResultSnd.m_szDescriptionEnglish );
  611. _tcscat( pSoundInfo->m_szNotesEnglish, TEXT("\r\n") );
  612. bProblem = TRUE;
  613. }
  614. else
  615. {
  616. LoadString(NULL, IDS_DSINSTRUCTIONS, sz, 500);
  617. _tcscat( pSoundInfo->m_szNotes, sz );
  618. LoadString(NULL, IDS_DSINSTRUCTIONS_ENGLISH, sz, 500);
  619. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  620. }
  621. if (!bProblem)
  622. {
  623. LoadString(NULL, IDS_NOPROBLEM, sz, 500);
  624. _tcscat( pSoundInfo->m_szNotes, sz );
  625. LoadString(NULL, IDS_NOPROBLEM_ENGLISH, sz, 500);
  626. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  627. }
  628. }
  629. }