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.

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