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.

744 lines
27 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. _tcsncpy(pSoundInfoNew->m_szDescription, pszDescription, 200);
  141. pSoundInfoNew->m_szDescription[199] = 0;
  142. if (s_pKSPS == NULL)
  143. {
  144. // Without the DSound private interface, we can't use it to get
  145. // waveout device ID or devnode. Assume device ID is 0, and use
  146. // waveOutMessage(DRV_QUERYDEVNODE) to get dev node.
  147. waveOutMessage((HWAVEOUT)0, DRV_QUERYDEVNODE, (DWORD_PTR)&pSoundInfoNew->m_dwDevnode, 0);
  148. pSoundInfoNew->m_lwAccelerationLevel = -1;
  149. }
  150. else
  151. {
  152. pSoundInfoNew->m_dwDevnode = pdsdData->Devnode;
  153. if (pdsdData->Type == 0)
  154. LoadString(NULL, IDS_EMULATED, pSoundInfoNew->m_szType, 100);
  155. else if (pdsdData->Type == 1)
  156. LoadString(NULL, IDS_VXD, pSoundInfoNew->m_szType, 100);
  157. else if (pdsdData->Type == 2)
  158. LoadString(NULL, IDS_WDM, pSoundInfoNew->m_szType, 100);
  159. DIRECTSOUNDBASICACCELERATION_LEVEL accelLevel;
  160. if (FAILED(PrvGetBasicAcceleration(s_pKSPS, *pGuid, &accelLevel)))
  161. pSoundInfoNew->m_lwAccelerationLevel = -1;
  162. else
  163. pSoundInfoNew->m_lwAccelerationLevel = (LONG)accelLevel;
  164. // This will only work on DX7 and beyond
  165. GetRegKey(s_pKSPS, *pGuid, pSoundInfoNew->m_szRegKey);
  166. }
  167. WAVEOUTCAPS waveoutcaps;
  168. LONG devID;
  169. if (pdsdData == NULL)
  170. devID = 0;
  171. else
  172. devID = pdsdData->WaveDeviceId;
  173. if (MMSYSERR_NOERROR == waveOutGetDevCaps(devID, &waveoutcaps, sizeof(waveoutcaps)))
  174. {
  175. // May want to use mmreg.h to add strings for manufacturer/product names here
  176. wsprintf(pSoundInfoNew->m_szManufacturerID, TEXT("%d"), waveoutcaps.wMid);
  177. wsprintf(pSoundInfoNew->m_szProductID, TEXT("%d"), waveoutcaps.wPid);
  178. }
  179. // Sometimes, pszModule is the full path. Sometimes it's just the leaf.
  180. // Sometimes, it's something inbetween. Separate the leaf, and look
  181. // in a few different places.
  182. TCHAR* pszLeaf;
  183. pszLeaf = _tcsrchr(pszModule, TEXT('\\'));
  184. if (pszLeaf == NULL)
  185. {
  186. lstrcpy(pSoundInfoNew->m_szDriverName, pszModule);
  187. }
  188. else
  189. {
  190. lstrcpy(pSoundInfoNew->m_szDriverName, (pszLeaf + 1));
  191. }
  192. // Try just module string
  193. int nLenMod = lstrlen(pszModule);
  194. _tcsncpy(pSoundInfoNew->m_szDriverPath, pszModule, 500);
  195. pSoundInfoNew->m_szDriverPath[499]=0;
  196. if (pszLeaf == NULL || GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  197. {
  198. // Try windows dir + module string
  199. if( GetWindowsDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH) != 0 )
  200. {
  201. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\"));
  202. if( lstrlen(pSoundInfoNew->m_szDriverPath) + nLenMod < 500 )
  203. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  204. if (GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  205. {
  206. // Try system dir + module string
  207. if( GetSystemDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH) != 0 )
  208. {
  209. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\"));
  210. if( lstrlen(pSoundInfoNew->m_szDriverPath) + nLenMod < 500 )
  211. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  212. if (GetFileAttributes(pSoundInfoNew->m_szDriverPath) == 0xFFFFFFFF)
  213. {
  214. // Try windows dir + \system32\drivers\ + module string
  215. if( GetWindowsDirectory(pSoundInfoNew->m_szDriverPath, MAX_PATH) != 0 )
  216. {
  217. lstrcat(pSoundInfoNew->m_szDriverPath, TEXT("\\System32\\Drivers\\"));
  218. if( lstrlen(pSoundInfoNew->m_szDriverPath) + nLenMod < 500 )
  219. lstrcat(pSoundInfoNew->m_szDriverPath, pszModule);
  220. }
  221. }
  222. }
  223. }
  224. }
  225. }
  226. PrvReleaseDeviceDescription( pdsdData );
  227. return TRUE;
  228. }
  229. /****************************************************************************
  230. *
  231. * GetExtraSoundInfo
  232. *
  233. ****************************************************************************/
  234. HRESULT GetExtraSoundInfo(SoundInfo* pSoundInfoFirst)
  235. {
  236. SoundInfo* pSoundInfo;
  237. BOOL bNT = BIsPlatformNT();
  238. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  239. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  240. {
  241. CheckRegistry(&pSoundInfo->m_pRegErrorFirst);
  242. if (bNT)
  243. GetRegSoundInfoNT(pSoundInfo);
  244. else
  245. GetRegSoundInfo9x(pSoundInfo);
  246. // Bug 18245: Try to distinguish between the various IBM MWave cards
  247. if (_tcsstr(pSoundInfo->m_szDeviceID, TEXT("MWAVEAUDIO_0460")) != NULL)
  248. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Stingray)"));
  249. else if (_tcsstr(pSoundInfo->m_szDeviceID, TEXT("MWAVEAUDIO_0465")) != NULL)
  250. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Marlin)"));
  251. else
  252. {
  253. TCHAR szBoard[100];
  254. lstrcpy( szBoard, TEXT("") );
  255. GetPrivateProfileString(TEXT("Mwave,Board"), TEXT("board"), TEXT(""),
  256. szBoard, 100, TEXT("MWave.ini"));
  257. if (lstrcmp(szBoard, TEXT("MWAT-046")) == 0)
  258. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Dolphin)"));
  259. else if (lstrcmp(szBoard, TEXT("MWAT-043")) == 0)
  260. lstrcat(pSoundInfo->m_szDescription, TEXT(" (Whale)"));
  261. }
  262. // Sometimes, like when a sound driver is emulated, the driver
  263. // will be reported as something like "WaveOut 0". In this case,
  264. // just blank out the file-related fields.
  265. if (_tcsstr(pSoundInfo->m_szDriverName, TEXT(".")) == NULL)
  266. {
  267. lstrcpy(pSoundInfo->m_szDriverName, TEXT(""));
  268. lstrcpy(pSoundInfo->m_szDriverPath, TEXT(""));
  269. }
  270. else
  271. {
  272. GetFileVersion(pSoundInfo->m_szDriverPath, pSoundInfo->m_szDriverVersion,
  273. pSoundInfo->m_szDriverAttributes, pSoundInfo->m_szDriverLanguageLocal, pSoundInfo->m_szDriverLanguage,
  274. &pSoundInfo->m_bDriverBeta, &pSoundInfo->m_bDriverDebug);
  275. FileIsSigned(pSoundInfo->m_szDriverPath, &pSoundInfo->m_bDriverSigned, &pSoundInfo->m_bDriverSignedValid);
  276. GetFileDateAndSize(pSoundInfo->m_szDriverPath,
  277. pSoundInfo->m_szDriverDateLocal, pSoundInfo->m_szDriverDate, &pSoundInfo->m_numBytes);
  278. }
  279. }
  280. return S_OK;
  281. }
  282. /****************************************************************************
  283. *
  284. * GetRegSoundInfo9x
  285. *
  286. ****************************************************************************/
  287. VOID GetRegSoundInfo9x(SoundInfo* pSoundInfo)
  288. {
  289. HKEY hkey = NULL;
  290. DWORD iKey = 0;
  291. TCHAR szSubKey[200];
  292. DWORD dwSubKeySize;
  293. TCHAR szClass[100];
  294. DWORD dwClassSize;
  295. HKEY hkeySub = NULL;
  296. DWORD dwDevnode;
  297. DWORD cb;
  298. DWORD dwType;
  299. HKEY hkeyOther = NULL;
  300. // We have the DevNode, so find the device in the registry with the
  301. // matching DevNode and gather more info there.
  302. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\control\\MediaResources\\wave"),
  303. 0, KEY_READ, &hkey))
  304. {
  305. while (TRUE)
  306. {
  307. dwSubKeySize = sizeof(szSubKey);
  308. dwClassSize = sizeof(szClass);
  309. if (ERROR_SUCCESS != RegEnumKeyEx(hkey, iKey, szSubKey, &dwSubKeySize, NULL, szClass, &dwClassSize, NULL))
  310. break;
  311. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szSubKey, 0, KEY_READ, &hkeySub))
  312. {
  313. cb = sizeof(dwDevnode);
  314. if (ERROR_SUCCESS == RegQueryValueEx(hkeySub, TEXT("DevNode"), NULL, &dwType, (BYTE*)&dwDevnode, &cb))
  315. {
  316. if (dwDevnode == pSoundInfo->m_dwDevnode)
  317. {
  318. // Found match...gather yummy info
  319. cb = sizeof(pSoundInfo->m_szDeviceID);
  320. RegQueryValueEx(hkeySub, TEXT("DeviceID"), NULL, &dwType, (BYTE*)pSoundInfo->m_szDeviceID, &cb);
  321. // Occasionally the driver name that DirectSoundEnumerate spits out
  322. // is garbage (as with my Crystal SoundFusion). If that's the case,
  323. // use the driver name listed here instead.
  324. if (lstrlen(pSoundInfo->m_szDriverName) < 4)
  325. {
  326. cb = sizeof(pSoundInfo->m_szDriverName);
  327. RegQueryValueEx(hkeySub, TEXT("Driver"), NULL, &dwType, (BYTE*)pSoundInfo->m_szDriverName, &cb);
  328. GetSystemDirectory(pSoundInfo->m_szDriverPath, MAX_PATH);
  329. lstrcat(pSoundInfo->m_szDriverPath, TEXT("\\"));
  330. if( lstrlen(pSoundInfo->m_szDriverPath) + lstrlen(pSoundInfo->m_szDriverName) < 500 )
  331. lstrcat(pSoundInfo->m_szDriverPath, pSoundInfo->m_szDriverName);
  332. }
  333. TCHAR szOtherKey[300];
  334. cb = sizeof(szOtherKey);
  335. RegQueryValueEx(hkeySub, TEXT("SOFTWAREKEY"), NULL, &dwType, (BYTE*)szOtherKey, &cb);
  336. if (lstrlen(szOtherKey) > 0)
  337. {
  338. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szOtherKey, 0, KEY_READ, &hkeyOther))
  339. {
  340. cb = sizeof(pSoundInfo->m_szOtherDrivers);
  341. RegQueryValueEx(hkeyOther, TEXT("Driver"), NULL, &dwType, (BYTE*)pSoundInfo->m_szOtherDrivers, &cb);
  342. cb = sizeof(pSoundInfo->m_szProvider);
  343. RegQueryValueEx(hkeyOther, TEXT("ProviderName"), NULL, &dwType, (BYTE*)pSoundInfo->m_szProvider, &cb);
  344. RegCloseKey(hkeyOther);
  345. }
  346. }
  347. }
  348. }
  349. RegCloseKey(hkeySub);
  350. }
  351. iKey++;
  352. }
  353. RegCloseKey(hkey);
  354. }
  355. }
  356. /****************************************************************************
  357. *
  358. * GetRegSoundInfoNT
  359. *
  360. ****************************************************************************/
  361. VOID GetRegSoundInfoNT(SoundInfo* pSoundInfo)
  362. {
  363. TCHAR szFullKey[300];
  364. HKEY hkey;
  365. DWORD cbData;
  366. DWORD dwType;
  367. TCHAR szDriverKey[300];
  368. TCHAR szOtherFullKey[300];
  369. lstrcpy(szFullKey, TEXT("System\\CurrentControlSet\\Enum\\"));
  370. lstrcat(szFullKey, pSoundInfo->m_szRegKey);
  371. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hkey))
  372. {
  373. cbData = sizeof(pSoundInfo->m_szDeviceID);
  374. RegQueryValueEx(hkey, TEXT("HardwareID"), 0, &dwType, (LPBYTE)pSoundInfo->m_szDeviceID, &cbData);
  375. cbData = sizeof(szDriverKey);
  376. RegQueryValueEx(hkey, TEXT("Driver"), 0, &dwType, (LPBYTE)szDriverKey, &cbData);
  377. RegCloseKey(hkey);
  378. }
  379. lstrcpy(szOtherFullKey, TEXT("System\\CurrentControlSet\\Control\\Class\\"));
  380. lstrcat(szOtherFullKey, szDriverKey);
  381. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szOtherFullKey, 0, KEY_READ, &hkey))
  382. {
  383. cbData = sizeof(pSoundInfo->m_szProvider);
  384. RegQueryValueEx(hkey, TEXT("ProviderName"), 0, &dwType, (LPBYTE)pSoundInfo->m_szProvider, &cbData);
  385. RegCloseKey(hkey);
  386. }
  387. }
  388. /****************************************************************************
  389. *
  390. * GetDSSoundInfo
  391. *
  392. ****************************************************************************/
  393. HRESULT GetDSSoundInfo(SoundInfo* pSoundInfoFirst)
  394. {
  395. HRESULT hr;
  396. HRESULT hrRet = S_OK;
  397. SoundInfo* pSoundInfo;
  398. TCHAR szPath[MAX_PATH];
  399. HINSTANCE hInstDSound;
  400. LPDIRECTSOUNDCREATE pDSCreate;
  401. GetSystemDirectory(szPath, MAX_PATH);
  402. lstrcat(szPath, TEXT("\\dsound.dll"));
  403. hInstDSound = LoadLibrary(szPath);
  404. if (hInstDSound == NULL)
  405. return E_FAIL;
  406. pDSCreate = (LPDIRECTSOUNDCREATE)GetProcAddress(hInstDSound, "DirectSoundCreate");
  407. if (pDSCreate == NULL)
  408. {
  409. FreeLibrary(hInstDSound);
  410. return E_FAIL;
  411. }
  412. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  413. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  414. {
  415. if (FAILED(hr = GetDirectSoundInfo(pDSCreate, pSoundInfo)))
  416. hrRet = hr; // but keep going
  417. }
  418. FreeLibrary(hInstDSound);
  419. return hrRet;
  420. }
  421. /****************************************************************************
  422. *
  423. * IsDriverWDM
  424. *
  425. ****************************************************************************/
  426. BOOL IsDriverWDM( TCHAR* szDriverName )
  427. {
  428. if( _tcsstr( szDriverName, TEXT(".sys") ) == NULL )
  429. return FALSE;
  430. else
  431. return TRUE;
  432. }
  433. /****************************************************************************
  434. *
  435. * GetDirectSoundInfo
  436. *
  437. ****************************************************************************/
  438. HRESULT GetDirectSoundInfo(LPDIRECTSOUNDCREATE pDSCreate, SoundInfo* pSoundInfo)
  439. {
  440. HRESULT hr;
  441. LPDIRECTSOUND pds = NULL;
  442. GUID* pGUID;
  443. DSCAPS dscaps;
  444. // Right now, this function only calls DSCreate/GetCaps to determine if
  445. // the driver is signed. If we have already determined that it is by
  446. // other means, don't bother with this test.
  447. if (pSoundInfo->m_bDriverSigned)
  448. return S_OK;
  449. // Bug 29918: If this is a WDM driver, then don't call GetCaps() since
  450. // on DX7.1+ GetCaps() will always return DSCAPS_CERTIFIED on WDM drivers
  451. if( IsDriverWDM( pSoundInfo->m_szDriverName ) )
  452. return S_OK;
  453. if (pSoundInfo->m_guid == GUID_NULL)
  454. pGUID = NULL;
  455. else
  456. pGUID = &pSoundInfo->m_guid;
  457. if (FAILED(hr = pDSCreate(pGUID, &pds, NULL)))
  458. goto LFail;
  459. dscaps.dwSize = sizeof(dscaps);
  460. if (FAILED(hr = pds->GetCaps(&dscaps)))
  461. goto LFail;
  462. pSoundInfo->m_bDriverSignedValid = TRUE;
  463. if (dscaps.dwFlags & DSCAPS_CERTIFIED)
  464. pSoundInfo->m_bDriverSigned = TRUE;
  465. pds->Release();
  466. return S_OK;
  467. LFail:
  468. if (pds != NULL)
  469. pds->Release();
  470. return hr;
  471. }
  472. /****************************************************************************
  473. *
  474. * ChangeAccelerationLevel
  475. *
  476. ****************************************************************************/
  477. HRESULT ChangeAccelerationLevel(SoundInfo* pSoundInfo, LONG lwLevel)
  478. {
  479. HRESULT hr = S_OK;
  480. DIRECTSOUNDBASICACCELERATION_LEVEL level = (DIRECTSOUNDBASICACCELERATION_LEVEL)lwLevel;
  481. LPKSPROPERTYSET pksps = NULL;
  482. TCHAR szPath[MAX_PATH];
  483. HINSTANCE hInstDSound = NULL;
  484. GetSystemDirectory(szPath, MAX_PATH);
  485. lstrcat(szPath, TEXT("\\dsound.dll"));
  486. hInstDSound = LoadLibrary(szPath);
  487. if (hInstDSound == NULL)
  488. {
  489. hr = DDERR_NOTFOUND;
  490. goto LEnd;
  491. }
  492. if (FAILED(hr = DirectSoundPrivateCreate(&pksps)))
  493. goto LEnd;
  494. if (FAILED(hr = PrvSetBasicAcceleration(pksps, pSoundInfo->m_guid, level)))
  495. goto LEnd;
  496. LEnd:
  497. if (pksps != NULL)
  498. pksps->Release();
  499. if (hInstDSound != NULL)
  500. FreeLibrary(hInstDSound);
  501. pSoundInfo->m_lwAccelerationLevel = lwLevel;
  502. return hr;
  503. }
  504. /****************************************************************************
  505. *
  506. * CheckRegistry
  507. *
  508. ****************************************************************************/
  509. HRESULT CheckRegistry(RegError** ppRegErrorFirst)
  510. {
  511. HRESULT hr;
  512. HKEY HKCR = HKEY_CLASSES_ROOT;
  513. TCHAR szVersion[100];
  514. HKEY hkey;
  515. DWORD cbData;
  516. ULONG ulType;
  517. DWORD dwMajor = 0;
  518. DWORD dwMinor = 0;
  519. DWORD dwRevision = 0;
  520. DWORD dwBuild = 0;
  521. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectX"),
  522. 0, KEY_READ, &hkey))
  523. {
  524. cbData = 100;
  525. RegQueryValueEx(hkey, TEXT("Version"), 0, &ulType, (LPBYTE)szVersion, &cbData);
  526. RegCloseKey(hkey);
  527. if (lstrlen(szVersion) > 6 &&
  528. lstrlen(szVersion) < 20)
  529. {
  530. if( _stscanf(szVersion, TEXT("%d.%d.%d.%d"), &dwMajor, &dwMinor, &dwRevision, &dwBuild) != 4 )
  531. {
  532. dwMajor = 0;
  533. dwMinor = 0;
  534. dwRevision = 0;
  535. dwBuild = 0;
  536. }
  537. }
  538. }
  539. // No registry checking on DX versions before DX7
  540. if (dwMinor < 7)
  541. return S_OK;
  542. // From dsound.inf:
  543. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSound"), TEXT(""), TEXT("*"))))
  544. return hr;
  545. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSound\\CLSID"), TEXT(""), TEXT("{47D4D946-62E8-11cf-93BC-444553540000}"))))
  546. return hr;
  547. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}"), TEXT(""), TEXT("*"))))
  548. return hr;
  549. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}\\InprocServer32"), TEXT(""), TEXT("dsound.dll"), CRF_LEAF)))
  550. return hr;
  551. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{47D4D946-62E8-11cf-93BC-444553540000}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  552. return hr;
  553. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSoundCapture"), TEXT(""), TEXT("*"))))
  554. return hr;
  555. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("DirectSoundCapture\\CLSID"), TEXT(""), TEXT("{B0210780-89CD-11d0-AF08-00A0C925CD16}"))))
  556. return hr;
  557. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}"), TEXT(""), TEXT("*"))))
  558. return hr;
  559. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}\\InprocServer32"), TEXT(""), TEXT("dsound.dll"), CRF_LEAF)))
  560. return hr;
  561. if (FAILED(hr = CheckRegString(ppRegErrorFirst, HKCR, TEXT("CLSID\\{B0210780-89CD-11d0-AF08-00A0C925CD16}\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Both"))))
  562. return hr;
  563. return S_OK;
  564. }
  565. /****************************************************************************
  566. *
  567. * DestroySoundInfo
  568. *
  569. ****************************************************************************/
  570. VOID DestroySoundInfo(SoundInfo* pSoundInfoFirst)
  571. {
  572. SoundInfo* pSoundInfo;
  573. SoundInfo* pSoundInfoNext;
  574. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  575. pSoundInfo = pSoundInfoNext)
  576. {
  577. DestroyReg( &pSoundInfo->m_pRegErrorFirst );
  578. pSoundInfoNext = pSoundInfo->m_pSoundInfoNext;
  579. delete pSoundInfo;
  580. }
  581. }
  582. /****************************************************************************
  583. *
  584. * DiagnoseSound
  585. *
  586. ****************************************************************************/
  587. VOID DiagnoseSound(SoundInfo* pSoundInfoFirst)
  588. {
  589. SoundInfo* pSoundInfo;
  590. TCHAR sz[500];
  591. TCHAR szFmt[500];
  592. for (pSoundInfo = pSoundInfoFirst; pSoundInfo != NULL;
  593. pSoundInfo = pSoundInfo->m_pSoundInfoNext)
  594. {
  595. _tcscpy( pSoundInfo->m_szNotes, TEXT("") );
  596. _tcscpy( pSoundInfo->m_szNotesEnglish, TEXT("") );
  597. // Report any problems:
  598. BOOL bProblem = FALSE;
  599. if ( pSoundInfo->m_bDriverSignedValid &&
  600. !pSoundInfo->m_bDriverSigned &&
  601. lstrlen(pSoundInfo->m_szDriverName) > 0)
  602. {
  603. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1, szFmt, 300);
  604. wsprintf(sz, szFmt, pSoundInfo->m_szDriverName);
  605. _tcscat( pSoundInfo->m_szNotes, sz );
  606. LoadString(NULL, IDS_UNSIGNEDDRIVERFMT1_ENGLISH, szFmt, 300);
  607. wsprintf(sz, szFmt, pSoundInfo->m_szDriverName);
  608. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  609. bProblem = TRUE;
  610. }
  611. if (pSoundInfo->m_pRegErrorFirst != NULL)
  612. {
  613. LoadString(NULL, IDS_REGISTRYPROBLEM, sz, 500);
  614. _tcscat( pSoundInfo->m_szNotes, sz );
  615. LoadString(NULL, IDS_REGISTRYPROBLEM_ENGLISH, sz, 500);
  616. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  617. bProblem = TRUE;
  618. }
  619. // Report any DSound test results:
  620. if (pSoundInfo->m_testResultSnd.m_bStarted &&
  621. !pSoundInfo->m_testResultSnd.m_bCancelled)
  622. {
  623. LoadString(NULL, IDS_DSRESULTS, sz, 500);
  624. _tcscat( pSoundInfo->m_szNotes, sz );
  625. _tcscat( pSoundInfo->m_szNotes, pSoundInfo->m_testResultSnd.m_szDescription );
  626. _tcscat( pSoundInfo->m_szNotes, TEXT("\r\n") );
  627. LoadString(NULL, IDS_DSRESULTS_ENGLISH, sz, 500);
  628. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  629. _tcscat( pSoundInfo->m_szNotesEnglish, pSoundInfo->m_testResultSnd.m_szDescriptionEnglish );
  630. _tcscat( pSoundInfo->m_szNotesEnglish, TEXT("\r\n") );
  631. bProblem = TRUE;
  632. }
  633. else
  634. {
  635. LoadString(NULL, IDS_DSINSTRUCTIONS, sz, 500);
  636. _tcscat( pSoundInfo->m_szNotes, sz );
  637. LoadString(NULL, IDS_DSINSTRUCTIONS_ENGLISH, sz, 500);
  638. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  639. }
  640. if (!bProblem)
  641. {
  642. LoadString(NULL, IDS_NOPROBLEM, sz, 500);
  643. _tcscat( pSoundInfo->m_szNotes, sz );
  644. LoadString(NULL, IDS_NOPROBLEM_ENGLISH, sz, 500);
  645. _tcscat( pSoundInfo->m_szNotesEnglish, sz );
  646. }
  647. }
  648. }