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.

1413 lines
37 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. mmedia.c
  5. Abstract:
  6. Multimedia settings migration functions for Win2000
  7. Author:
  8. Calin Negreanu (calinn) 02-Dec-1997
  9. Revision History:
  10. Ovidiu Temereanca (ovidiut) 29-Jan-1999
  11. Ovidiu Temereanca (ovidiut) 05-Apr-1999 See NT bug 313357 for the story of all #if 0
  12. --*/
  13. #include "pch.h"
  14. #include "mmediap.h"
  15. #include <initguid.h>
  16. #include <dsound.h>
  17. #include <dsprv.h> // windows\inc
  18. POOLHANDLE g_MmediaPool = NULL;
  19. #define MM_POOLGETMEM(STRUCT,COUNT) (STRUCT*)PoolMemGetMemory(g_MmediaPool,COUNT*sizeof(STRUCT))
  20. static PCTSTR g_UserData = NULL;
  21. static HKEY g_UserRoot = NULL;
  22. typedef HRESULT (STDAPICALLTYPE *PFNDLLGETCLASSOBJECT)(REFCLSID, REFIID, LPVOID FAR*);
  23. BOOL
  24. pRestoreSystemValue (
  25. IN PCTSTR KeyName,
  26. IN PCTSTR Field, OPTIONAL
  27. IN PCTSTR StrValue, OPTIONAL
  28. OUT PDWORD NumValue
  29. )
  30. {
  31. TCHAR Key[MEMDB_MAX];
  32. MemDbBuildKey (Key, MEMDB_CATEGORY_MMEDIA_SYSTEM, KeyName, Field, StrValue);
  33. return MemDbGetValue (Key, NumValue);
  34. }
  35. PVOID
  36. pRestoreSystemBinaryValue (
  37. IN PCTSTR KeyName,
  38. IN PCTSTR Field, OPTIONAL
  39. OUT PDWORD DataSize
  40. )
  41. {
  42. TCHAR Key[MEMDB_MAX];
  43. MemDbBuildKey (Key, MEMDB_CATEGORY_MMEDIA_SYSTEM, KeyName, Field, NULL);
  44. return (PVOID)MemDbGetBinaryValue (Key, DataSize);
  45. }
  46. BOOL
  47. pRestoreMMSystemMixerSettings (
  48. VOID
  49. )
  50. {
  51. #if 0
  52. UINT MixerID, MixerMaxID;
  53. HMIXER mixer;
  54. MIXERCAPS mixerCaps;
  55. MIXERLINE mixerLine, mixerLineSource;
  56. MIXERLINECONTROLS mixerLineControls;
  57. MIXERCONTROL* pmxControl;
  58. MIXERCONTROLDETAILS mixerControlDetails;
  59. LONG rc;
  60. DWORD Dest, Src, Control;
  61. TCHAR MixerKey[MAX_PATH], LineKey[MAX_PATH], SrcKey[MAX_PATH], SubKey[MAX_PATH];
  62. DWORD ValuesCount;
  63. DWORD Value;
  64. PVOID SetData;
  65. BOOL b;
  66. if (!pRestoreSystemValue (S_MIXERNUMDEVS, NULL, NULL, &MixerMaxID)) {
  67. return FALSE;
  68. }
  69. MixerID = mixerGetNumDevs ();
  70. if (!MixerID) {
  71. DEBUGMSG ((DBG_MMEDIA, "pRestoreMMSystemMixerSettings: mixerGetNumDevs returned 0"));
  72. return FALSE;
  73. }
  74. if (MixerMaxID != MixerID) {
  75. return FALSE;
  76. }
  77. for (MixerID = 0; MixerID < MixerMaxID; MixerID++) {
  78. rc = mixerGetDevCaps (MixerID, &mixerCaps, sizeof (MIXERCAPS));
  79. if (rc != MMSYSERR_NOERROR) {
  80. DEBUGMSG ((DBG_MMEDIA, "mixerGetDevCaps failed for mixer %lu [rc=%#X]. No settings will be restored.", MixerID, rc));
  81. continue;
  82. }
  83. wsprintf (MixerKey, S_MIXERID, MixerID);
  84. if (!pRestoreSystemValue (MixerKey, S_NUMLINES, NULL, &Value)) {
  85. continue;
  86. }
  87. if (mixerCaps.cDestinations > Value) {
  88. //
  89. // only try to restore first Value lines
  90. //
  91. mixerCaps.cDestinations = Value;
  92. }
  93. rc = mixerOpen (&mixer, MixerID, 0L, 0L, MIXER_OBJECTF_MIXER);
  94. if (rc != MMSYSERR_NOERROR) {
  95. DEBUGMSG ((DBG_MMEDIA, "mixerOpen failed for mixer %lu [rc=%#X]. No settings will be restored.", MixerID, rc));
  96. continue;
  97. }
  98. for (Dest = 0; Dest < mixerCaps.cDestinations; Dest++) {
  99. ZeroMemory (&mixerLine, sizeof (MIXERLINE));
  100. mixerLine.cbStruct = sizeof (MIXERLINE);
  101. mixerLine.dwDestination = Dest;
  102. rc = mixerGetLineInfo ((HMIXEROBJ)mixer, &mixerLine, MIXER_GETLINEINFOF_DESTINATION);
  103. if (rc == MMSYSERR_NOERROR) {
  104. wsprintf (LineKey, S_LINEID, Dest);
  105. b = pRestoreSystemValue (MixerKey, LineKey, S_NUMSOURCES, &Value) &&
  106. Value == mixerLine.cConnections;
  107. b = b &&
  108. pRestoreSystemValue (MixerKey, LineKey, S_NUMCONTROLS, &Value) &&
  109. Value == mixerLine.cControls;
  110. if (b && mixerLine.cControls > 0) {
  111. //
  112. // get all control values for the destination
  113. //
  114. ZeroMemory (&mixerLineControls, sizeof (MIXERLINECONTROLS));
  115. mixerLineControls.cbStruct = sizeof (MIXERLINECONTROLS);
  116. mixerLineControls.dwLineID = mixerLine.dwLineID;
  117. mixerLineControls.cControls = mixerLine.cControls;
  118. mixerLineControls.cbmxctrl = sizeof (MIXERCONTROL);
  119. mixerLineControls.pamxctrl = MM_POOLGETMEM (MIXERCONTROL, mixerLineControls.cControls);
  120. if (mixerLineControls.pamxctrl) {
  121. rc = mixerGetLineControls((HMIXEROBJ)mixer, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL);
  122. if (rc == MMSYSERR_NOERROR) {
  123. for (
  124. Control = 0, pmxControl = mixerLineControls.pamxctrl;
  125. Control < mixerLineControls.cControls;
  126. Control++, pmxControl++
  127. ) {
  128. ZeroMemory (&mixerControlDetails, sizeof (MIXERCONTROLDETAILS));
  129. mixerControlDetails.cbStruct = sizeof (MIXERCONTROLDETAILS);
  130. mixerControlDetails.dwControlID = pmxControl->dwControlID;
  131. mixerControlDetails.cMultipleItems = pmxControl->cMultipleItems;
  132. mixerControlDetails.cChannels = mixerLine.cChannels;
  133. if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) {
  134. mixerControlDetails.cChannels = 1;
  135. }
  136. ValuesCount = mixerControlDetails.cChannels;
  137. if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE) {
  138. ValuesCount *= mixerControlDetails.cMultipleItems;
  139. }
  140. mixerControlDetails.cbDetails = sizeof (DWORD);
  141. wsprintf (SubKey, TEXT("%s\\%lu"), LineKey, Control);
  142. SetData = pRestoreSystemBinaryValue (MixerKey, SubKey, &Value);
  143. if (SetData &&
  144. Value == ValuesCount * mixerControlDetails.cbDetails
  145. ) {
  146. mixerControlDetails.paDetails = SetData;
  147. rc = mixerSetControlDetails ((HMIXEROBJ)mixer, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
  148. if (rc != MMSYSERR_NOERROR) {
  149. DEBUGMSG ((DBG_MMEDIA, "mixerSetControlDetails failed for mixer %lu, Line=%lu, Ctl=%lu [rc=%#X]", MixerID, Dest, Control, rc));
  150. }
  151. }
  152. }
  153. } else {
  154. DEBUGMSG ((DBG_MMEDIA, "mixerGetLineControls failed for mixer %lu, Line=%#X [rc=%#X].", MixerID, mixerLineControls.dwLineID, rc));
  155. }
  156. }
  157. }
  158. //
  159. // set this information for all source connections
  160. //
  161. for (Src = 0; Src < mixerLine.cConnections; Src++) {
  162. ZeroMemory (&mixerLineSource, sizeof (MIXERLINE));
  163. mixerLineSource.cbStruct = sizeof(MIXERLINE);
  164. mixerLineSource.dwDestination = Dest;
  165. mixerLineSource.dwSource = Src;
  166. rc = mixerGetLineInfo((HMIXEROBJ)mixer, &mixerLineSource, MIXER_GETLINEINFOF_SOURCE);
  167. if (rc == MMSYSERR_NOERROR) {
  168. wsprintf (SrcKey, S_SRCID, Src);
  169. wsprintf (SubKey, TEXT("%s\\%s"), SrcKey, S_NUMCONTROLS);
  170. if (!pRestoreSystemValue (MixerKey, LineKey, SubKey, &Value) ||
  171. Value != mixerLineSource.cControls ||
  172. mixerLineSource.cControls <= 0
  173. ) {
  174. continue;
  175. }
  176. //
  177. // set all control values
  178. //
  179. ZeroMemory (&mixerLineControls, sizeof (MIXERLINECONTROLS));
  180. mixerLineControls.cbStruct = sizeof (MIXERLINECONTROLS);
  181. mixerLineControls.dwLineID = mixerLineSource.dwLineID;
  182. mixerLineControls.cControls = mixerLineSource.cControls;
  183. mixerLineControls.cbmxctrl = sizeof (MIXERCONTROL);
  184. mixerLineControls.pamxctrl = MM_POOLGETMEM (MIXERCONTROL, mixerLineControls.cControls);
  185. if (mixerLineControls.pamxctrl) {
  186. rc = mixerGetLineControls((HMIXEROBJ)mixer, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL);
  187. if (rc == MMSYSERR_NOERROR) {
  188. for (
  189. Control = 0, pmxControl = mixerLineControls.pamxctrl;
  190. Control < mixerLineControls.cControls;
  191. Control++, pmxControl++
  192. ) {
  193. ZeroMemory (&mixerControlDetails, sizeof (MIXERCONTROLDETAILS));
  194. mixerControlDetails.cbStruct = sizeof (MIXERCONTROLDETAILS);
  195. mixerControlDetails.dwControlID = pmxControl->dwControlID;
  196. mixerControlDetails.cMultipleItems = pmxControl->cMultipleItems;
  197. mixerControlDetails.cChannels = mixerLineSource.cChannels;
  198. if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) {
  199. mixerControlDetails.cChannels = 1;
  200. }
  201. ValuesCount = mixerControlDetails.cChannels;
  202. if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE) {
  203. ValuesCount *= mixerControlDetails.cMultipleItems;
  204. }
  205. mixerControlDetails.cbDetails = sizeof (DWORD);
  206. wsprintf (SubKey, TEXT("%s\\%s\\%lu"), LineKey, SrcKey, Control);
  207. SetData = pRestoreSystemBinaryValue (MixerKey, SubKey, &Value);
  208. if (SetData &&
  209. Value == ValuesCount * mixerControlDetails.cbDetails
  210. ) {
  211. mixerControlDetails.paDetails = SetData;
  212. rc = mixerSetControlDetails ((HMIXEROBJ)mixer, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
  213. if (rc != MMSYSERR_NOERROR) {
  214. DEBUGMSG ((DBG_MMEDIA, "mixerSetControlDetails failed for mixer %lu, Line=%lu, Src=%lu, Ctl=%lu [rc=%#X]", MixerID, Dest, Src, Control, rc));
  215. }
  216. }
  217. }
  218. } else {
  219. DEBUGMSG ((DBG_MMEDIA, "mixerGetLineControls failed for mixer %lu, Src=%lu, Line=%#X [rc=%#X].", MixerID, Src, mixerLineControls.dwLineID, rc));
  220. }
  221. }
  222. } else {
  223. DEBUGMSG ((DBG_MMEDIA, "mixerGetLineInfo failed for mixer %lu, Src=%lu [rc=%#X].", MixerID, Src, rc));
  224. }
  225. }
  226. } else {
  227. DEBUGMSG ((DBG_MMEDIA, "mixerGetLineInfo failed for mixer %lu [rc=%#X]. No settings will be preserved.", MixerID, rc));
  228. }
  229. }
  230. mixerClose (mixer);
  231. }
  232. #endif
  233. return TRUE;
  234. }
  235. BOOL
  236. CALLBACK
  237. pDSDeviceCountCallback (
  238. IN PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pDSDescData,
  239. IN LPVOID UserData
  240. )
  241. {
  242. PDWORD pWaveDeviceCount;
  243. //
  244. // don't count emulated devices
  245. //
  246. if (pDSDescData->Type == DIRECTSOUNDDEVICE_TYPE_EMULATED) {
  247. return TRUE;
  248. }
  249. pWaveDeviceCount = (PDWORD)UserData;
  250. if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
  251. pWaveDeviceCount[0]++;
  252. } else if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
  253. pWaveDeviceCount[1]++;
  254. }
  255. return TRUE;
  256. }
  257. BOOL
  258. pGetDSWaveCount (
  259. IN LPKSPROPERTYSET pKsPropertySet,
  260. OUT PDWORD pWaveDeviceCount
  261. )
  262. {
  263. DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA Data;
  264. pWaveDeviceCount[0] = pWaveDeviceCount[1] = 0;
  265. Data.Callback = pDSDeviceCountCallback;
  266. Data.Context = pWaveDeviceCount;
  267. if (FAILED (IKsPropertySet_Get (
  268. pKsPropertySet,
  269. &DSPROPSETID_DirectSoundDevice,
  270. DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
  271. NULL,
  272. 0,
  273. &Data,
  274. sizeof(Data),
  275. NULL
  276. ))) {
  277. return FALSE;
  278. }
  279. return TRUE;
  280. }
  281. typedef struct {
  282. DWORD HWLevel;
  283. DWORD SRCLevel;
  284. DWORD SpeakerConfig;
  285. DWORD SpeakerType;
  286. } DS_DATA, *PDS_DATA;
  287. typedef struct {
  288. DWORD HWLevel;
  289. DWORD SRCLevel;
  290. } DSC_DATA, *PDSC_DATA;
  291. BOOL
  292. pRestoreDSValues (
  293. IN DWORD DeviceID,
  294. OUT PDS_DATA DSData
  295. )
  296. {
  297. TCHAR Device[MAX_PATH];
  298. wsprintf (Device, S_WAVEID, DeviceID);
  299. if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_ACCELERATION, &DSData->HWLevel)) {
  300. return FALSE;
  301. }
  302. if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SRCQUALITY, &DSData->SRCLevel)) {
  303. return FALSE;
  304. }
  305. if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SPEAKERCONFIG, &DSData->SpeakerConfig)) {
  306. return FALSE;
  307. }
  308. if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SPEAKERTYPE, &DSData->SpeakerType)) {
  309. return FALSE;
  310. }
  311. return TRUE;
  312. }
  313. BOOL
  314. pRestoreDSCValues (
  315. IN DWORD DeviceID,
  316. OUT PDSC_DATA DSCData
  317. )
  318. {
  319. TCHAR Device[MAX_PATH];
  320. wsprintf (Device, S_WAVEID, DeviceID);
  321. if (!pRestoreSystemValue (Device, S_DIRECTSOUNDCAPTURE, S_ACCELERATION, &DSCData->HWLevel)) {
  322. return FALSE;
  323. }
  324. if (!pRestoreSystemValue (Device, S_DIRECTSOUNDCAPTURE, S_SRCQUALITY, &DSCData->SRCLevel)) {
  325. return FALSE;
  326. }
  327. return TRUE;
  328. }
  329. BOOL
  330. pSetDSValues (
  331. IN LPKSPROPERTYSET pKsPropertySet,
  332. IN REFGUID DeviceGuid,
  333. IN const PDS_DATA Data
  334. )
  335. {
  336. DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION_DATA BasicAcceleration;
  337. DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY_DATA SrcQuality;
  338. DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA_DATA SpeakerConfig;
  339. DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA_DATA SpeakerType;
  340. HRESULT hr;
  341. BasicAcceleration.DeviceId = *DeviceGuid;
  342. BasicAcceleration.Level = (DIRECTSOUNDBASICACCELERATION_LEVEL)Data->HWLevel;
  343. hr = IKsPropertySet_Set (
  344. pKsPropertySet,
  345. &DSPROPSETID_DirectSoundBasicAcceleration,
  346. DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION,
  347. NULL,
  348. 0,
  349. &BasicAcceleration,
  350. sizeof(BasicAcceleration)
  351. );
  352. if(SUCCEEDED (hr)) {
  353. SrcQuality.DeviceId = *DeviceGuid;
  354. SrcQuality.Quality = (DIRECTSOUNDMIXER_SRCQUALITY)Data->SRCLevel;
  355. hr = IKsPropertySet_Set (
  356. pKsPropertySet,
  357. &DSPROPSETID_DirectSoundMixer,
  358. DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY,
  359. NULL,
  360. 0,
  361. &SrcQuality,
  362. sizeof(SrcQuality)
  363. );
  364. }
  365. if(SUCCEEDED (hr)) {
  366. SpeakerConfig.DeviceId = *DeviceGuid;
  367. SpeakerConfig.SubKeyName = S_SPEAKERCONFIG;
  368. SpeakerConfig.ValueName = S_SPEAKERCONFIG;
  369. SpeakerConfig.RegistryDataType = REG_DWORD;
  370. SpeakerConfig.Data = &Data->SpeakerConfig;
  371. SpeakerConfig.DataSize = sizeof(Data->SpeakerConfig);
  372. hr = IKsPropertySet_Set (
  373. pKsPropertySet,
  374. &DSPROPSETID_DirectSoundPersistentData,
  375. DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA,
  376. NULL,
  377. 0,
  378. &SpeakerConfig,
  379. sizeof(SpeakerConfig)
  380. );
  381. }
  382. if(SUCCEEDED (hr)) {
  383. SpeakerType.DeviceId = *DeviceGuid;
  384. SpeakerType.SubKeyName = S_SPEAKERTYPE;
  385. SpeakerType.ValueName = S_SPEAKERTYPE;
  386. SpeakerType.RegistryDataType = REG_DWORD;
  387. SpeakerType.Data = &Data->SpeakerType;
  388. SpeakerType.DataSize = sizeof(Data->SpeakerType);
  389. hr = IKsPropertySet_Set (
  390. pKsPropertySet,
  391. &DSPROPSETID_DirectSoundPersistentData,
  392. DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA,
  393. NULL,
  394. 0,
  395. &SpeakerType,
  396. sizeof(SpeakerType)
  397. );
  398. }
  399. return SUCCEEDED (hr);
  400. }
  401. BOOL
  402. pSetDSCValues (
  403. IN LPKSPROPERTYSET pKsPropertySet,
  404. IN REFGUID DeviceGuid,
  405. IN const PDSC_DATA Data
  406. )
  407. {
  408. DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION_DATA BasicAcceleration;
  409. DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY_DATA SrcQuality;
  410. HRESULT hr;
  411. BasicAcceleration.DeviceId = *DeviceGuid;
  412. BasicAcceleration.Level = (DIRECTSOUNDBASICACCELERATION_LEVEL)Data->HWLevel;
  413. hr = IKsPropertySet_Set (
  414. pKsPropertySet,
  415. &DSPROPSETID_DirectSoundBasicAcceleration,
  416. DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION,
  417. NULL,
  418. 0,
  419. &BasicAcceleration,
  420. sizeof(BasicAcceleration)
  421. );
  422. if(SUCCEEDED (hr)) {
  423. SrcQuality.DeviceId = *DeviceGuid;
  424. SrcQuality.Quality = (DIRECTSOUNDMIXER_SRCQUALITY)Data->SRCLevel;
  425. hr = IKsPropertySet_Set (
  426. pKsPropertySet,
  427. &DSPROPSETID_DirectSoundMixer,
  428. DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY,
  429. NULL,
  430. 0,
  431. &SrcQuality,
  432. sizeof(SrcQuality)
  433. );
  434. }
  435. return SUCCEEDED (hr);
  436. }
  437. BOOL
  438. CALLBACK
  439. pRestoreDeviceSettings (
  440. IN PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pDSDescData,
  441. IN LPVOID UserData
  442. )
  443. {
  444. LPKSPROPERTYSET pKsPropertySet = (LPKSPROPERTYSET)UserData;
  445. DS_DATA DSData;
  446. DSC_DATA DSCData;
  447. if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
  448. if (pRestoreDSValues (pDSDescData->WaveDeviceId, &DSData)) {
  449. pSetDSValues (
  450. pKsPropertySet,
  451. &pDSDescData->DeviceId,
  452. &DSData
  453. );
  454. }
  455. } else if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
  456. if (pRestoreDSCValues (pDSDescData->WaveDeviceId, &DSCData)) {
  457. pSetDSCValues (
  458. pKsPropertySet,
  459. &pDSDescData->DeviceId,
  460. &DSCData
  461. );
  462. }
  463. }
  464. return TRUE;
  465. }
  466. BOOL
  467. pRestoreWaveDevicesDSSettings (
  468. IN LPKSPROPERTYSET pKsPropertySet
  469. )
  470. {
  471. DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA Data;
  472. HRESULT hr;
  473. DWORD WaveNumDevs;
  474. //
  475. // array of 2 longs; first counts wave-out devices, second wave-ins
  476. //
  477. DWORD WaveDeviceCount[2];
  478. if (!pGetDSWaveCount (pKsPropertySet, WaveDeviceCount)) {
  479. return FALSE;
  480. }
  481. if (!pRestoreSystemValue (S_WAVENUMDEVS, NULL, NULL, &WaveNumDevs)) {
  482. return FALSE;
  483. }
  484. if (WaveDeviceCount[0] != WaveNumDevs || WaveDeviceCount[1] != WaveNumDevs) {
  485. DEBUGMSG ((DBG_MMEDIA, "pRestoreWaveDevicesDSSettings: number of wave devices changed, no settings will be restored"));
  486. return FALSE;
  487. }
  488. Data.Callback = pRestoreDeviceSettings;
  489. Data.Context = pKsPropertySet;
  490. hr = IKsPropertySet_Get (
  491. pKsPropertySet,
  492. &DSPROPSETID_DirectSoundDevice,
  493. DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
  494. NULL,
  495. 0,
  496. &Data,
  497. sizeof(Data),
  498. NULL
  499. );
  500. return SUCCEEDED (hr);
  501. }
  502. BOOL
  503. pDirectSoundPrivateCreate (
  504. IN HINSTANCE LibDsound,
  505. OUT LPKSPROPERTYSET* ppKsPropertySet
  506. )
  507. {
  508. PFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
  509. LPCLASSFACTORY pClassFactory = NULL;
  510. LPKSPROPERTYSET pKsPropertySet = NULL;
  511. HRESULT hr = DS_OK;
  512. pfnDllGetClassObject = (PFNDLLGETCLASSOBJECT)GetProcAddress (
  513. LibDsound,
  514. "DllGetClassObject"
  515. );
  516. if(!pfnDllGetClassObject) {
  517. hr = DSERR_GENERIC;
  518. }
  519. if(SUCCEEDED(hr)) {
  520. hr = pfnDllGetClassObject (
  521. &CLSID_DirectSoundPrivate,
  522. &IID_IClassFactory,
  523. (LPVOID*)&pClassFactory
  524. );
  525. }
  526. //
  527. // Create the DirectSoundPrivate object and query for an IKsPropertySet interface
  528. //
  529. if(SUCCEEDED(hr)) {
  530. hr = pClassFactory->lpVtbl->CreateInstance (
  531. pClassFactory,
  532. NULL,
  533. &IID_IKsPropertySet,
  534. (LPVOID*)&pKsPropertySet
  535. );
  536. }
  537. // Release the class factory
  538. if(pClassFactory) {
  539. pClassFactory->lpVtbl->Release (pClassFactory);
  540. }
  541. // Handle final success or failure
  542. if(SUCCEEDED(hr)) {
  543. *ppKsPropertySet = pKsPropertySet;
  544. }
  545. else if(pKsPropertySet) {
  546. IKsPropertySet_Release (pKsPropertySet);
  547. }
  548. return SUCCEEDED (hr);
  549. }
  550. BOOL
  551. pRestoreMMSystemDirectSound (
  552. VOID
  553. )
  554. {
  555. #if 0
  556. HINSTANCE LibDsound = NULL;
  557. LPKSPROPERTYSET pKsPropertySet;
  558. BOOL b = FALSE;
  559. LibDsound = LoadLibrary (S_DSOUNDLIB);
  560. if(LibDsound) {
  561. if (pDirectSoundPrivateCreate (LibDsound, &pKsPropertySet)) {
  562. b = pRestoreWaveDevicesDSSettings (pKsPropertySet);
  563. IKsPropertySet_Release (pKsPropertySet);
  564. }
  565. FreeLibrary (LibDsound);
  566. }
  567. return b;
  568. #endif
  569. return TRUE;
  570. }
  571. BOOL
  572. pRestoreMMSystemCDSettings (
  573. VOID
  574. )
  575. {
  576. DWORD Unit, Volume;
  577. HKEY key, keyUnit;
  578. BYTE defDrive[4] = {0,0,0,0};
  579. BYTE defVolume[8] = {0,0,0,0,0,0,0,0};
  580. TCHAR unitKeyStr [MAX_TCHAR_PATH];
  581. LONG rc;
  582. BOOL b = FALSE;
  583. if (pRestoreSystemValue (S_CDROM, S_DEFAULTDRIVE, NULL, &Unit)) {
  584. defDrive [0] = (BYTE)Unit;
  585. key = CreateRegKey (HKEY_LOCAL_MACHINE, S_SKEY_CDAUDIO);
  586. if (key) {
  587. rc = RegSetValueEx (key, S_DEFAULTDRIVE, 0, REG_BINARY, defDrive, sizeof(defDrive));
  588. if (rc == ERROR_SUCCESS) {
  589. if (pRestoreSystemValue (S_CDROM, S_VOLUMESETTINGS, NULL, &Volume)) {
  590. wsprintf (unitKeyStr, S_SKEY_CDUNIT, Unit);
  591. keyUnit = CreateRegKey (HKEY_LOCAL_MACHINE, unitKeyStr);
  592. if (keyUnit) {
  593. defVolume [4] = (BYTE)Volume;
  594. rc = RegSetValueEx (
  595. keyUnit,
  596. S_VOLUMESETTINGS,
  597. 0,
  598. REG_BINARY,
  599. defVolume,
  600. sizeof(defVolume)
  601. );
  602. b = (rc == ERROR_SUCCESS);
  603. CloseRegKey (keyUnit);
  604. }
  605. }
  606. }
  607. CloseRegKey (key);
  608. }
  609. }
  610. return b;
  611. }
  612. BOOL
  613. pRestoreMMSystemMCISoundSettings (
  614. VOID
  615. )
  616. {
  617. TCHAR DriverName[MAX_PATH], Param[2];
  618. DWORD Size, Value;
  619. HKEY KeyMCI32;
  620. BOOL b = FALSE;
  621. LONG rc;
  622. rc = TrackedRegOpenKeyEx (HKEY_LOCAL_MACHINE, S_SKEY_WINNT_MCI, 0, KEY_READ, &KeyMCI32);
  623. if (rc == ERROR_SUCCESS) {
  624. Size = sizeof (DriverName);
  625. rc = RegQueryValueEx (KeyMCI32, S_WAVEAUDIO, NULL, NULL, (LPBYTE)DriverName, &Size);
  626. if (rc == ERROR_SUCCESS) {
  627. if (pRestoreSystemValue (S_MCI, S_WAVEAUDIO, NULL, &Value)) {
  628. if (Value >= 2 && Value <= 9) {
  629. wsprintf (Param, TEXT("%lu"), Value);
  630. if (WriteProfileString (DriverName, S_WAVEAUDIO, Param)) {
  631. b = TRUE;
  632. }
  633. }
  634. }
  635. }
  636. CloseRegKey (KeyMCI32);
  637. }
  638. return b;
  639. }
  640. BOOL
  641. pRestoreUserValue (
  642. IN PCTSTR KeyName,
  643. IN PCTSTR Field, OPTIONAL
  644. IN PCTSTR StrValue, OPTIONAL
  645. OUT PDWORD NumValue
  646. )
  647. /*++
  648. Routine Description:
  649. pRestoreUserValue gets a numeric value from MemDB database,
  650. specific for the current user.
  651. Arguments:
  652. KeyName - Specifies the name of key
  653. Field - Specifies an optional field
  654. StrValue - Specifies an optional value name
  655. NumValue - Receives the value, if present
  656. Return Value:
  657. TRUE if value was present and read successfully, FALSE if not
  658. --*/
  659. {
  660. TCHAR Key[MEMDB_MAX];
  661. MemDbBuildKey (Key, g_UserData, KeyName, Field, StrValue);
  662. return MemDbGetValue (Key, NumValue);
  663. }
  664. BOOL
  665. pRestoreMMUserPreferredOnly (
  666. VOID
  667. )
  668. /*++
  669. Routine Description:
  670. pRestoreMMUserPreferredOnly restores user's preference to use only
  671. selected devices for playback and record
  672. Arguments:
  673. none
  674. Return Value:
  675. TRUE if settings were restored properly
  676. --*/
  677. {
  678. HKEY soundMapperKey;
  679. DWORD preferredOnly;
  680. LONG rc;
  681. BOOL b = FALSE;
  682. if (pRestoreUserValue (S_AUDIO, S_PREFERREDONLY, NULL, &preferredOnly)) {
  683. soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
  684. if (soundMapperKey != NULL) {
  685. rc = RegSetValueEx (
  686. soundMapperKey,
  687. S_PREFERREDONLY,
  688. 0,
  689. REG_DWORD,
  690. (PCBYTE)&preferredOnly,
  691. sizeof (preferredOnly)
  692. );
  693. b = (rc == ERROR_SUCCESS);
  694. CloseRegKey (soundMapperKey);
  695. }
  696. }
  697. return b;
  698. }
  699. BOOL
  700. pRestoreMMUserShowVolume (
  701. VOID
  702. )
  703. /*++
  704. Routine Description:
  705. pRestoreMMUserShowVolume restores user's preference to have Volume settings
  706. displayed on the taskbar or not
  707. Arguments:
  708. none
  709. Return Value:
  710. TRUE if settings were restored properly
  711. --*/
  712. {
  713. HKEY sysTrayKey;
  714. DWORD ShowVolume;
  715. PDWORD Services;
  716. LONG rc;
  717. BOOL b = FALSE;
  718. if (pRestoreUserValue (S_AUDIO, S_SHOWVOLUME, NULL, &ShowVolume)) {
  719. sysTrayKey = CreateRegKey (g_UserRoot, S_SKEY_SYSTRAY);
  720. if (sysTrayKey != NULL) {
  721. Services = GetRegValueDword (sysTrayKey, S_SERVICES);
  722. if (Services != NULL) {
  723. if (ShowVolume) {
  724. *Services |= SERVICE_SHOWVOLUME;
  725. } else {
  726. *Services &= ~SERVICE_SHOWVOLUME;
  727. }
  728. rc = RegSetValueEx (
  729. sysTrayKey,
  730. S_SERVICES,
  731. 0,
  732. REG_DWORD,
  733. (PCBYTE)Services,
  734. sizeof (*Services)
  735. );
  736. b = (rc == ERROR_SUCCESS);
  737. MemFreeWrapper (Services);
  738. }
  739. CloseRegKey (sysTrayKey);
  740. }
  741. }
  742. return b;
  743. }
  744. BOOL
  745. pRestoreMMUserVideoSettings (
  746. VOID
  747. )
  748. /*++
  749. Routine Description:
  750. pRestoreMMUserVideoSettings restores user's preferred Video for Windows settings.
  751. Arguments:
  752. none
  753. Return Value:
  754. TRUE if settings were restored properly
  755. --*/
  756. {
  757. HKEY videoSetKey;
  758. DWORD VideoSettings;
  759. LONG rc;
  760. BOOL b = FALSE;
  761. if (pRestoreUserValue (S_VIDEO, S_VIDEOSETTINGS, NULL, &VideoSettings)) {
  762. videoSetKey = CreateRegKey (g_UserRoot, S_SKEY_VIDEOUSER);
  763. if (videoSetKey != NULL) {
  764. rc = RegSetValueEx (
  765. videoSetKey,
  766. S_DEFAULTOPTIONS,
  767. 0,
  768. REG_DWORD,
  769. (PCBYTE)&VideoSettings,
  770. sizeof (VideoSettings)
  771. );
  772. b = (rc == ERROR_SUCCESS);
  773. CloseRegKey (videoSetKey);
  774. }
  775. }
  776. return b;
  777. }
  778. BOOL
  779. pRestoreMMUserPreferredPlayback (
  780. VOID
  781. )
  782. /*++
  783. Routine Description:
  784. pRestoreMMUserPreferredPlayback restores user's preferred playback device.
  785. If the system doesn't have at least 2 wave out devices, nothing is changed.
  786. If there are multiple devices, selection is based on the device ID number,
  787. which is supposed to be left unchanged.
  788. Arguments:
  789. none
  790. Return Value:
  791. TRUE if settings were restored properly
  792. --*/
  793. {
  794. #if 0
  795. HKEY soundMapperKey;
  796. UINT waveOutNumDevs;
  797. DWORD UserPlayback, Value;
  798. WAVEOUTCAPS waveOutCaps;
  799. LONG rc;
  800. BOOL b = FALSE;
  801. waveOutNumDevs = waveOutGetNumDevs();
  802. if (!waveOutNumDevs) {
  803. DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserPreferredPlayback: waveOutGetNumDevs returned 0"));
  804. return FALSE;
  805. }
  806. if (waveOutNumDevs <= 1) {
  807. return TRUE;
  808. }
  809. if (!pRestoreSystemValue (S_WAVEOUTNUMDEVS, NULL, NULL, &Value) ||
  810. Value != (DWORD)waveOutNumDevs) {
  811. return FALSE;
  812. }
  813. if (pRestoreUserValue (S_AUDIO, S_PREFERREDPLAY, NULL, &UserPlayback)) {
  814. rc = waveOutGetDevCaps (UserPlayback, &waveOutCaps, sizeof (waveOutCaps));
  815. if (rc == MMSYSERR_NOERROR) {
  816. soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
  817. if (soundMapperKey != NULL) {
  818. rc = RegSetValueEx (
  819. soundMapperKey,
  820. S_PLAYBACK,
  821. 0,
  822. REG_SZ,
  823. (PCBYTE)waveOutCaps.szPname,
  824. SizeOfString (waveOutCaps.szPname)
  825. );
  826. b = (rc == ERROR_SUCCESS);
  827. CloseRegKey (soundMapperKey);
  828. }
  829. }
  830. }
  831. return b;
  832. #endif
  833. return TRUE;
  834. }
  835. BOOL
  836. pRestoreMMUserPreferredRecord (
  837. VOID
  838. )
  839. /*++
  840. Routine Description:
  841. pRestoreMMUserPreferredRecord restores user's preferred record device.
  842. If the system doesn't have at least 2 wave in devices, nothing is changed.
  843. If there are multiple devices, selection is based on the device ID number,
  844. which is supposed to be left unchanged.
  845. Arguments:
  846. none
  847. Return Value:
  848. TRUE if settings were restored properly
  849. --*/
  850. {
  851. #if 0
  852. HKEY soundMapperKey;
  853. UINT waveInNumDevs;
  854. DWORD UserRecord, Value;
  855. WAVEINCAPS waveInCaps;
  856. LONG rc;
  857. BOOL b = FALSE;
  858. waveInNumDevs = waveInGetNumDevs();
  859. if (!waveInNumDevs) {
  860. DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserPreferredRecord: waveInGetNumDevs returned 0"));
  861. return FALSE;
  862. }
  863. if (waveInNumDevs <= 1) {
  864. return TRUE;
  865. }
  866. if (!pRestoreSystemValue (S_WAVEINNUMDEVS, NULL, NULL, &Value) ||
  867. Value != (DWORD)waveInNumDevs) {
  868. return FALSE;
  869. }
  870. if (pRestoreUserValue (S_AUDIO, S_PREFERREDREC, NULL, &UserRecord)) {
  871. rc = waveInGetDevCaps (UserRecord, &waveInCaps, sizeof (waveInCaps));
  872. if (rc == MMSYSERR_NOERROR) {
  873. soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
  874. if (soundMapperKey != NULL) {
  875. rc = RegSetValueEx (
  876. soundMapperKey,
  877. S_RECORD,
  878. 0,
  879. REG_SZ,
  880. (PCBYTE)waveInCaps.szPname,
  881. SizeOfString (waveInCaps.szPname)
  882. );
  883. b = (rc == ERROR_SUCCESS);
  884. CloseRegKey (soundMapperKey);
  885. }
  886. }
  887. }
  888. return b;
  889. #endif
  890. return TRUE;
  891. }
  892. BOOL
  893. pRestoreMMUserSndVol32 (
  894. VOID
  895. )
  896. /*++
  897. Routine Description:
  898. pRestoreMMUserSndVol32 restores SndVol32 options for the current user
  899. Arguments:
  900. none
  901. Return Value:
  902. TRUE if settings were restored properly
  903. --*/
  904. {
  905. HKEY Options;
  906. PDWORD Style;
  907. DWORD NewStyle;
  908. BOOL ShowAdvanced;
  909. #if 0
  910. HKEY VolControl, MixerKey;
  911. DWORD Value;
  912. UINT MixerID, MixerMaxID;
  913. MIXERCAPS mixerCaps;
  914. TCHAR MixerNum[MAX_PATH];
  915. LONG rc;
  916. #endif
  917. if (pRestoreUserValue (S_SNDVOL32, S_SHOWADVANCED, NULL, &ShowAdvanced)) {
  918. Options = CreateRegKey (g_UserRoot, S_SKEY_VOLCTL_OPTIONS);
  919. if (Options != NULL) {
  920. Style = GetRegValueDword (Options, S_STYLE);
  921. if (Style != NULL) {
  922. NewStyle = *Style;
  923. MemFreeWrapper (Style);
  924. } else {
  925. NewStyle = 0;
  926. }
  927. if (ShowAdvanced) {
  928. NewStyle |= STYLE_SHOWADVANCED;
  929. } else {
  930. NewStyle &= ~STYLE_SHOWADVANCED;
  931. }
  932. RegSetValueEx (
  933. Options,
  934. S_STYLE,
  935. 0,
  936. REG_DWORD,
  937. (PCBYTE)&NewStyle,
  938. sizeof (NewStyle)
  939. );
  940. CloseRegKey (Options);
  941. }
  942. }
  943. #if 0
  944. //
  945. // restore window position for each mixer device
  946. //
  947. if (!pRestoreSystemValue (S_MIXERNUMDEVS, NULL, NULL, &MixerMaxID)) {
  948. return FALSE;
  949. }
  950. MixerID = mixerGetNumDevs ();
  951. if (!MixerID) {
  952. DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserSndVol32: mixerGetNumDevs returned 0"));
  953. return FALSE;
  954. }
  955. if (MixerMaxID != MixerID) {
  956. return FALSE;
  957. }
  958. VolControl = CreateRegKey (g_UserRoot, S_SKEY_VOLUMECONTROL);
  959. if (VolControl != NULL) {
  960. for (MixerID = 0; MixerID < MixerMaxID; MixerID++) {
  961. rc = mixerGetDevCaps (MixerID, &mixerCaps, sizeof (MIXERCAPS));
  962. if (rc == MMSYSERR_NOERROR) {
  963. wsprintf (MixerNum, S_MIXERID, MixerID);
  964. MixerKey = CreateRegKey (VolControl, mixerCaps.szPname);
  965. if (MixerKey) {
  966. if (pRestoreUserValue (S_SNDVOL32, MixerNum, S_X, &Value)) {
  967. RegSetValueEx (
  968. MixerKey,
  969. S_X,
  970. 0,
  971. REG_DWORD,
  972. (PCBYTE)&Value,
  973. sizeof (Value)
  974. );
  975. }
  976. if (pRestoreUserValue (S_SNDVOL32, MixerNum, S_Y, &Value)) {
  977. RegSetValueEx (
  978. MixerKey,
  979. S_Y,
  980. 0,
  981. REG_DWORD,
  982. (PCBYTE)&Value,
  983. sizeof (Value)
  984. );
  985. }
  986. CloseRegKey (MixerKey);
  987. }
  988. }
  989. }
  990. CloseRegKey (VolControl);
  991. }
  992. #endif
  993. return TRUE;
  994. }
  995. BOOL
  996. pPreserveCurrentSoundScheme (
  997. VOID
  998. )
  999. {
  1000. HKEY Sounds;
  1001. LONG rc = E_FAIL;
  1002. //
  1003. // if WinMM finds HKCU\Control Panel\Sounds [SystemDefault] = ","
  1004. // it doesn't override user's current sound scheme
  1005. //
  1006. Sounds = CreateRegKey (g_UserRoot, S_SKEY_CPANEL_SOUNDS);
  1007. if (Sounds != NULL) {
  1008. rc = RegSetValueEx (
  1009. Sounds,
  1010. S_SYSTEMDEFAULT,
  1011. 0,
  1012. REG_SZ,
  1013. (PCBYTE)S_DUMMYVALUE,
  1014. SizeOfString (S_DUMMYVALUE)
  1015. );
  1016. CloseRegKey (Sounds);
  1017. }
  1018. return rc == ERROR_SUCCESS;
  1019. }
  1020. #define DEFMAC(Item) pRestore##Item,
  1021. static MM_SETTING_ACTION g_MMRestoreSystemSettings [] = {
  1022. MM_SYSTEM_SETTINGS
  1023. };
  1024. static MM_SETTING_ACTION g_MMRestoreUserSettings [] = {
  1025. MM_USER_SETTINGS
  1026. };
  1027. #undef DEFMAC
  1028. BOOL
  1029. RestoreMMSettings_System (
  1030. VOID
  1031. )
  1032. {
  1033. int i;
  1034. g_MmediaPool = PoolMemInitNamedPool ("MMediaNT");
  1035. if (!g_MmediaPool) {
  1036. return FALSE;
  1037. }
  1038. for (i = 0; i < sizeof (g_MMRestoreSystemSettings) / sizeof (MM_SETTING_ACTION); i++) {
  1039. (* g_MMRestoreSystemSettings[i]) ();
  1040. }
  1041. PoolMemDestroyPool (g_MmediaPool);
  1042. g_MmediaPool = NULL;
  1043. return TRUE;
  1044. }
  1045. BOOL
  1046. RestoreMMSettings_User (
  1047. IN PCTSTR UserName,
  1048. IN HKEY UserRoot
  1049. )
  1050. {
  1051. INT i;
  1052. if (!UserName || UserName[0] == 0) {
  1053. return TRUE;
  1054. }
  1055. MYASSERT (g_UserData == NULL);
  1056. g_UserData = JoinPaths (MEMDB_CATEGORY_MMEDIA_USERS, UserName);
  1057. g_UserRoot = UserRoot;
  1058. __try {
  1059. for (i = 0; i < sizeof (g_MMRestoreUserSettings) / sizeof (MM_SETTING_ACTION); i++) {
  1060. (* g_MMRestoreUserSettings[i]) ();
  1061. }
  1062. //
  1063. // special action to prevent WinMM overriding current sound scheme
  1064. //
  1065. pPreserveCurrentSoundScheme ();
  1066. }
  1067. __finally {
  1068. FreePathString (g_UserData);
  1069. g_UserData = NULL;
  1070. g_UserRoot = NULL;
  1071. }
  1072. return TRUE;
  1073. }