1414 lines
37 KiB
C
1414 lines
37 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mmedia.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Multimedia settings migration functions for Win2000
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Calin Negreanu (calinn) 02-Dec-1997
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Ovidiu Temereanca (ovidiut) 29-Jan-1999
|
||
|
Ovidiu Temereanca (ovidiut) 05-Apr-1999 See NT bug 313357 for the story of all #if 0
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "mmediap.h"
|
||
|
|
||
|
#include <initguid.h>
|
||
|
#include <dsound.h>
|
||
|
#include <dsprv.h> // windows\inc
|
||
|
|
||
|
|
||
|
POOLHANDLE g_MmediaPool = NULL;
|
||
|
|
||
|
#define MM_POOLGETMEM(STRUCT,COUNT) (STRUCT*)PoolMemGetMemory(g_MmediaPool,COUNT*sizeof(STRUCT))
|
||
|
|
||
|
|
||
|
static PCTSTR g_UserData = NULL;
|
||
|
static HKEY g_UserRoot = NULL;
|
||
|
|
||
|
|
||
|
typedef HRESULT (STDAPICALLTYPE *PFNDLLGETCLASSOBJECT)(REFCLSID, REFIID, LPVOID FAR*);
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreSystemValue (
|
||
|
IN PCTSTR KeyName,
|
||
|
IN PCTSTR Field, OPTIONAL
|
||
|
IN PCTSTR StrValue, OPTIONAL
|
||
|
OUT PDWORD NumValue
|
||
|
)
|
||
|
{
|
||
|
TCHAR Key[MEMDB_MAX];
|
||
|
|
||
|
MemDbBuildKey (Key, MEMDB_CATEGORY_MMEDIA_SYSTEM, KeyName, Field, StrValue);
|
||
|
return MemDbGetValue (Key, NumValue);
|
||
|
}
|
||
|
|
||
|
|
||
|
PVOID
|
||
|
pRestoreSystemBinaryValue (
|
||
|
IN PCTSTR KeyName,
|
||
|
IN PCTSTR Field, OPTIONAL
|
||
|
OUT PDWORD DataSize
|
||
|
)
|
||
|
{
|
||
|
TCHAR Key[MEMDB_MAX];
|
||
|
|
||
|
MemDbBuildKey (Key, MEMDB_CATEGORY_MMEDIA_SYSTEM, KeyName, Field, NULL);
|
||
|
return (PVOID)MemDbGetBinaryValue (Key, DataSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMSystemMixerSettings (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
#if 0
|
||
|
|
||
|
UINT MixerID, MixerMaxID;
|
||
|
HMIXER mixer;
|
||
|
MIXERCAPS mixerCaps;
|
||
|
MIXERLINE mixerLine, mixerLineSource;
|
||
|
MIXERLINECONTROLS mixerLineControls;
|
||
|
MIXERCONTROL* pmxControl;
|
||
|
MIXERCONTROLDETAILS mixerControlDetails;
|
||
|
LONG rc;
|
||
|
DWORD Dest, Src, Control;
|
||
|
TCHAR MixerKey[MAX_PATH], LineKey[MAX_PATH], SrcKey[MAX_PATH], SubKey[MAX_PATH];
|
||
|
DWORD ValuesCount;
|
||
|
DWORD Value;
|
||
|
PVOID SetData;
|
||
|
BOOL b;
|
||
|
|
||
|
if (!pRestoreSystemValue (S_MIXERNUMDEVS, NULL, NULL, &MixerMaxID)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
MixerID = mixerGetNumDevs ();
|
||
|
if (!MixerID) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "pRestoreMMSystemMixerSettings: mixerGetNumDevs returned 0"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (MixerMaxID != MixerID) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (MixerID = 0; MixerID < MixerMaxID; MixerID++) {
|
||
|
|
||
|
rc = mixerGetDevCaps (MixerID, &mixerCaps, sizeof (MIXERCAPS));
|
||
|
if (rc != MMSYSERR_NOERROR) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerGetDevCaps failed for mixer %lu [rc=%#X]. No settings will be restored.", MixerID, rc));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
wsprintf (MixerKey, S_MIXERID, MixerID);
|
||
|
if (!pRestoreSystemValue (MixerKey, S_NUMLINES, NULL, &Value)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (mixerCaps.cDestinations > Value) {
|
||
|
//
|
||
|
// only try to restore first Value lines
|
||
|
//
|
||
|
mixerCaps.cDestinations = Value;
|
||
|
}
|
||
|
|
||
|
rc = mixerOpen (&mixer, MixerID, 0L, 0L, MIXER_OBJECTF_MIXER);
|
||
|
if (rc != MMSYSERR_NOERROR) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerOpen failed for mixer %lu [rc=%#X]. No settings will be restored.", MixerID, rc));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
for (Dest = 0; Dest < mixerCaps.cDestinations; Dest++) {
|
||
|
|
||
|
ZeroMemory (&mixerLine, sizeof (MIXERLINE));
|
||
|
|
||
|
mixerLine.cbStruct = sizeof (MIXERLINE);
|
||
|
mixerLine.dwDestination = Dest;
|
||
|
|
||
|
rc = mixerGetLineInfo ((HMIXEROBJ)mixer, &mixerLine, MIXER_GETLINEINFOF_DESTINATION);
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
wsprintf (LineKey, S_LINEID, Dest);
|
||
|
|
||
|
b = pRestoreSystemValue (MixerKey, LineKey, S_NUMSOURCES, &Value) &&
|
||
|
Value == mixerLine.cConnections;
|
||
|
|
||
|
b = b &&
|
||
|
pRestoreSystemValue (MixerKey, LineKey, S_NUMCONTROLS, &Value) &&
|
||
|
Value == mixerLine.cControls;
|
||
|
|
||
|
if (b && mixerLine.cControls > 0) {
|
||
|
//
|
||
|
// get all control values for the destination
|
||
|
//
|
||
|
ZeroMemory (&mixerLineControls, sizeof (MIXERLINECONTROLS));
|
||
|
|
||
|
mixerLineControls.cbStruct = sizeof (MIXERLINECONTROLS);
|
||
|
mixerLineControls.dwLineID = mixerLine.dwLineID;
|
||
|
mixerLineControls.cControls = mixerLine.cControls;
|
||
|
mixerLineControls.cbmxctrl = sizeof (MIXERCONTROL);
|
||
|
mixerLineControls.pamxctrl = MM_POOLGETMEM (MIXERCONTROL, mixerLineControls.cControls);
|
||
|
if (mixerLineControls.pamxctrl) {
|
||
|
|
||
|
rc = mixerGetLineControls((HMIXEROBJ)mixer, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL);
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
for (
|
||
|
Control = 0, pmxControl = mixerLineControls.pamxctrl;
|
||
|
Control < mixerLineControls.cControls;
|
||
|
Control++, pmxControl++
|
||
|
) {
|
||
|
|
||
|
ZeroMemory (&mixerControlDetails, sizeof (MIXERCONTROLDETAILS));
|
||
|
|
||
|
mixerControlDetails.cbStruct = sizeof (MIXERCONTROLDETAILS);
|
||
|
mixerControlDetails.dwControlID = pmxControl->dwControlID;
|
||
|
mixerControlDetails.cMultipleItems = pmxControl->cMultipleItems;
|
||
|
mixerControlDetails.cChannels = mixerLine.cChannels;
|
||
|
if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) {
|
||
|
mixerControlDetails.cChannels = 1;
|
||
|
}
|
||
|
ValuesCount = mixerControlDetails.cChannels;
|
||
|
if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE) {
|
||
|
ValuesCount *= mixerControlDetails.cMultipleItems;
|
||
|
}
|
||
|
mixerControlDetails.cbDetails = sizeof (DWORD);
|
||
|
wsprintf (SubKey, TEXT("%s\\%lu"), LineKey, Control);
|
||
|
SetData = pRestoreSystemBinaryValue (MixerKey, SubKey, &Value);
|
||
|
if (SetData &&
|
||
|
Value == ValuesCount * mixerControlDetails.cbDetails
|
||
|
) {
|
||
|
mixerControlDetails.paDetails = SetData;
|
||
|
rc = mixerSetControlDetails ((HMIXEROBJ)mixer, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
|
||
|
if (rc != MMSYSERR_NOERROR) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerSetControlDetails failed for mixer %lu, Line=%lu, Ctl=%lu [rc=%#X]", MixerID, Dest, Control, rc));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerGetLineControls failed for mixer %lu, Line=%#X [rc=%#X].", MixerID, mixerLineControls.dwLineID, rc));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set this information for all source connections
|
||
|
//
|
||
|
for (Src = 0; Src < mixerLine.cConnections; Src++) {
|
||
|
|
||
|
ZeroMemory (&mixerLineSource, sizeof (MIXERLINE));
|
||
|
|
||
|
mixerLineSource.cbStruct = sizeof(MIXERLINE);
|
||
|
mixerLineSource.dwDestination = Dest;
|
||
|
mixerLineSource.dwSource = Src;
|
||
|
|
||
|
rc = mixerGetLineInfo((HMIXEROBJ)mixer, &mixerLineSource, MIXER_GETLINEINFOF_SOURCE);
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
wsprintf (SrcKey, S_SRCID, Src);
|
||
|
wsprintf (SubKey, TEXT("%s\\%s"), SrcKey, S_NUMCONTROLS);
|
||
|
if (!pRestoreSystemValue (MixerKey, LineKey, SubKey, &Value) ||
|
||
|
Value != mixerLineSource.cControls ||
|
||
|
mixerLineSource.cControls <= 0
|
||
|
) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set all control values
|
||
|
//
|
||
|
ZeroMemory (&mixerLineControls, sizeof (MIXERLINECONTROLS));
|
||
|
|
||
|
mixerLineControls.cbStruct = sizeof (MIXERLINECONTROLS);
|
||
|
mixerLineControls.dwLineID = mixerLineSource.dwLineID;
|
||
|
mixerLineControls.cControls = mixerLineSource.cControls;
|
||
|
mixerLineControls.cbmxctrl = sizeof (MIXERCONTROL);
|
||
|
mixerLineControls.pamxctrl = MM_POOLGETMEM (MIXERCONTROL, mixerLineControls.cControls);
|
||
|
if (mixerLineControls.pamxctrl) {
|
||
|
|
||
|
rc = mixerGetLineControls((HMIXEROBJ)mixer, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL);
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
for (
|
||
|
Control = 0, pmxControl = mixerLineControls.pamxctrl;
|
||
|
Control < mixerLineControls.cControls;
|
||
|
Control++, pmxControl++
|
||
|
) {
|
||
|
|
||
|
ZeroMemory (&mixerControlDetails, sizeof (MIXERCONTROLDETAILS));
|
||
|
|
||
|
mixerControlDetails.cbStruct = sizeof (MIXERCONTROLDETAILS);
|
||
|
mixerControlDetails.dwControlID = pmxControl->dwControlID;
|
||
|
mixerControlDetails.cMultipleItems = pmxControl->cMultipleItems;
|
||
|
mixerControlDetails.cChannels = mixerLineSource.cChannels;
|
||
|
if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) {
|
||
|
mixerControlDetails.cChannels = 1;
|
||
|
}
|
||
|
ValuesCount = mixerControlDetails.cChannels;
|
||
|
if (pmxControl->fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE) {
|
||
|
ValuesCount *= mixerControlDetails.cMultipleItems;
|
||
|
}
|
||
|
mixerControlDetails.cbDetails = sizeof (DWORD);
|
||
|
wsprintf (SubKey, TEXT("%s\\%s\\%lu"), LineKey, SrcKey, Control);
|
||
|
SetData = pRestoreSystemBinaryValue (MixerKey, SubKey, &Value);
|
||
|
if (SetData &&
|
||
|
Value == ValuesCount * mixerControlDetails.cbDetails
|
||
|
) {
|
||
|
mixerControlDetails.paDetails = SetData;
|
||
|
rc = mixerSetControlDetails ((HMIXEROBJ)mixer, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
|
||
|
if (rc != MMSYSERR_NOERROR) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerSetControlDetails failed for mixer %lu, Line=%lu, Src=%lu, Ctl=%lu [rc=%#X]", MixerID, Dest, Src, Control, rc));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerGetLineControls failed for mixer %lu, Src=%lu, Line=%#X [rc=%#X].", MixerID, Src, mixerLineControls.dwLineID, rc));
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerGetLineInfo failed for mixer %lu, Src=%lu [rc=%#X].", MixerID, Src, rc));
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "mixerGetLineInfo failed for mixer %lu [rc=%#X]. No settings will be preserved.", MixerID, rc));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mixerClose (mixer);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CALLBACK
|
||
|
pDSDeviceCountCallback (
|
||
|
IN PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pDSDescData,
|
||
|
IN LPVOID UserData
|
||
|
)
|
||
|
{
|
||
|
PDWORD pWaveDeviceCount;
|
||
|
|
||
|
//
|
||
|
// don't count emulated devices
|
||
|
//
|
||
|
if (pDSDescData->Type == DIRECTSOUNDDEVICE_TYPE_EMULATED) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
pWaveDeviceCount = (PDWORD)UserData;
|
||
|
|
||
|
if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
|
||
|
|
||
|
pWaveDeviceCount[0]++;
|
||
|
|
||
|
} else if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
|
||
|
|
||
|
pWaveDeviceCount[1]++;
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetDSWaveCount (
|
||
|
IN LPKSPROPERTYSET pKsPropertySet,
|
||
|
OUT PDWORD pWaveDeviceCount
|
||
|
)
|
||
|
{
|
||
|
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA Data;
|
||
|
|
||
|
pWaveDeviceCount[0] = pWaveDeviceCount[1] = 0;
|
||
|
|
||
|
Data.Callback = pDSDeviceCountCallback;
|
||
|
Data.Context = pWaveDeviceCount;
|
||
|
if (FAILED (IKsPropertySet_Get (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundDevice,
|
||
|
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
|
||
|
NULL,
|
||
|
0,
|
||
|
&Data,
|
||
|
sizeof(Data),
|
||
|
NULL
|
||
|
))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
DWORD HWLevel;
|
||
|
DWORD SRCLevel;
|
||
|
DWORD SpeakerConfig;
|
||
|
DWORD SpeakerType;
|
||
|
} DS_DATA, *PDS_DATA;
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
DWORD HWLevel;
|
||
|
DWORD SRCLevel;
|
||
|
} DSC_DATA, *PDSC_DATA;
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreDSValues (
|
||
|
IN DWORD DeviceID,
|
||
|
OUT PDS_DATA DSData
|
||
|
)
|
||
|
{
|
||
|
TCHAR Device[MAX_PATH];
|
||
|
|
||
|
wsprintf (Device, S_WAVEID, DeviceID);
|
||
|
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_ACCELERATION, &DSData->HWLevel)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SRCQUALITY, &DSData->SRCLevel)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SPEAKERCONFIG, &DSData->SpeakerConfig)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUND, S_SPEAKERTYPE, &DSData->SpeakerType)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreDSCValues (
|
||
|
IN DWORD DeviceID,
|
||
|
OUT PDSC_DATA DSCData
|
||
|
)
|
||
|
{
|
||
|
TCHAR Device[MAX_PATH];
|
||
|
|
||
|
wsprintf (Device, S_WAVEID, DeviceID);
|
||
|
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUNDCAPTURE, S_ACCELERATION, &DSCData->HWLevel)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pRestoreSystemValue (Device, S_DIRECTSOUNDCAPTURE, S_SRCQUALITY, &DSCData->SRCLevel)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pSetDSValues (
|
||
|
IN LPKSPROPERTYSET pKsPropertySet,
|
||
|
IN REFGUID DeviceGuid,
|
||
|
IN const PDS_DATA Data
|
||
|
)
|
||
|
{
|
||
|
DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION_DATA BasicAcceleration;
|
||
|
DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY_DATA SrcQuality;
|
||
|
DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA_DATA SpeakerConfig;
|
||
|
DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA_DATA SpeakerType;
|
||
|
HRESULT hr;
|
||
|
|
||
|
BasicAcceleration.DeviceId = *DeviceGuid;
|
||
|
BasicAcceleration.Level = (DIRECTSOUNDBASICACCELERATION_LEVEL)Data->HWLevel;
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundBasicAcceleration,
|
||
|
DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION,
|
||
|
NULL,
|
||
|
0,
|
||
|
&BasicAcceleration,
|
||
|
sizeof(BasicAcceleration)
|
||
|
);
|
||
|
|
||
|
if(SUCCEEDED (hr)) {
|
||
|
SrcQuality.DeviceId = *DeviceGuid;
|
||
|
SrcQuality.Quality = (DIRECTSOUNDMIXER_SRCQUALITY)Data->SRCLevel;
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundMixer,
|
||
|
DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY,
|
||
|
NULL,
|
||
|
0,
|
||
|
&SrcQuality,
|
||
|
sizeof(SrcQuality)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED (hr)) {
|
||
|
SpeakerConfig.DeviceId = *DeviceGuid;
|
||
|
SpeakerConfig.SubKeyName = S_SPEAKERCONFIG;
|
||
|
SpeakerConfig.ValueName = S_SPEAKERCONFIG;
|
||
|
SpeakerConfig.RegistryDataType = REG_DWORD;
|
||
|
SpeakerConfig.Data = &Data->SpeakerConfig;
|
||
|
SpeakerConfig.DataSize = sizeof(Data->SpeakerConfig);
|
||
|
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundPersistentData,
|
||
|
DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA,
|
||
|
NULL,
|
||
|
0,
|
||
|
&SpeakerConfig,
|
||
|
sizeof(SpeakerConfig)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED (hr)) {
|
||
|
SpeakerType.DeviceId = *DeviceGuid;
|
||
|
SpeakerType.SubKeyName = S_SPEAKERTYPE;
|
||
|
SpeakerType.ValueName = S_SPEAKERTYPE;
|
||
|
SpeakerType.RegistryDataType = REG_DWORD;
|
||
|
SpeakerType.Data = &Data->SpeakerType;
|
||
|
SpeakerType.DataSize = sizeof(Data->SpeakerType);
|
||
|
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundPersistentData,
|
||
|
DSPROPERTY_DIRECTSOUNDPERSISTENTDATA_PERSISTDATA,
|
||
|
NULL,
|
||
|
0,
|
||
|
&SpeakerType,
|
||
|
sizeof(SpeakerType)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return SUCCEEDED (hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pSetDSCValues (
|
||
|
IN LPKSPROPERTYSET pKsPropertySet,
|
||
|
IN REFGUID DeviceGuid,
|
||
|
IN const PDSC_DATA Data
|
||
|
)
|
||
|
{
|
||
|
DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION_DATA BasicAcceleration;
|
||
|
DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY_DATA SrcQuality;
|
||
|
HRESULT hr;
|
||
|
|
||
|
BasicAcceleration.DeviceId = *DeviceGuid;
|
||
|
BasicAcceleration.Level = (DIRECTSOUNDBASICACCELERATION_LEVEL)Data->HWLevel;
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundBasicAcceleration,
|
||
|
DSPROPERTY_DIRECTSOUNDBASICACCELERATION_ACCELERATION,
|
||
|
NULL,
|
||
|
0,
|
||
|
&BasicAcceleration,
|
||
|
sizeof(BasicAcceleration)
|
||
|
);
|
||
|
|
||
|
if(SUCCEEDED (hr)) {
|
||
|
SrcQuality.DeviceId = *DeviceGuid;
|
||
|
SrcQuality.Quality = (DIRECTSOUNDMIXER_SRCQUALITY)Data->SRCLevel;
|
||
|
hr = IKsPropertySet_Set (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundMixer,
|
||
|
DSPROPERTY_DIRECTSOUNDMIXER_SRCQUALITY,
|
||
|
NULL,
|
||
|
0,
|
||
|
&SrcQuality,
|
||
|
sizeof(SrcQuality)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return SUCCEEDED (hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CALLBACK
|
||
|
pRestoreDeviceSettings (
|
||
|
IN PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA pDSDescData,
|
||
|
IN LPVOID UserData
|
||
|
)
|
||
|
{
|
||
|
LPKSPROPERTYSET pKsPropertySet = (LPKSPROPERTYSET)UserData;
|
||
|
DS_DATA DSData;
|
||
|
DSC_DATA DSCData;
|
||
|
|
||
|
if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
|
||
|
|
||
|
if (pRestoreDSValues (pDSDescData->WaveDeviceId, &DSData)) {
|
||
|
|
||
|
pSetDSValues (
|
||
|
pKsPropertySet,
|
||
|
&pDSDescData->DeviceId,
|
||
|
&DSData
|
||
|
);
|
||
|
}
|
||
|
|
||
|
} else if (pDSDescData->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
|
||
|
|
||
|
if (pRestoreDSCValues (pDSDescData->WaveDeviceId, &DSCData)) {
|
||
|
|
||
|
pSetDSCValues (
|
||
|
pKsPropertySet,
|
||
|
&pDSDescData->DeviceId,
|
||
|
&DSCData
|
||
|
);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreWaveDevicesDSSettings (
|
||
|
IN LPKSPROPERTYSET pKsPropertySet
|
||
|
)
|
||
|
{
|
||
|
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA Data;
|
||
|
HRESULT hr;
|
||
|
DWORD WaveNumDevs;
|
||
|
//
|
||
|
// array of 2 longs; first counts wave-out devices, second wave-ins
|
||
|
//
|
||
|
DWORD WaveDeviceCount[2];
|
||
|
|
||
|
if (!pGetDSWaveCount (pKsPropertySet, WaveDeviceCount)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pRestoreSystemValue (S_WAVENUMDEVS, NULL, NULL, &WaveNumDevs)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (WaveDeviceCount[0] != WaveNumDevs || WaveDeviceCount[1] != WaveNumDevs) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "pRestoreWaveDevicesDSSettings: number of wave devices changed, no settings will be restored"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Data.Callback = pRestoreDeviceSettings;
|
||
|
Data.Context = pKsPropertySet;
|
||
|
hr = IKsPropertySet_Get (
|
||
|
pKsPropertySet,
|
||
|
&DSPROPSETID_DirectSoundDevice,
|
||
|
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
|
||
|
NULL,
|
||
|
0,
|
||
|
&Data,
|
||
|
sizeof(Data),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
return SUCCEEDED (hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDirectSoundPrivateCreate (
|
||
|
IN HINSTANCE LibDsound,
|
||
|
OUT LPKSPROPERTYSET* ppKsPropertySet
|
||
|
)
|
||
|
{
|
||
|
PFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
|
||
|
LPCLASSFACTORY pClassFactory = NULL;
|
||
|
LPKSPROPERTYSET pKsPropertySet = NULL;
|
||
|
HRESULT hr = DS_OK;
|
||
|
|
||
|
pfnDllGetClassObject = (PFNDLLGETCLASSOBJECT)GetProcAddress (
|
||
|
LibDsound,
|
||
|
"DllGetClassObject"
|
||
|
);
|
||
|
if(!pfnDllGetClassObject) {
|
||
|
hr = DSERR_GENERIC;
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr)) {
|
||
|
hr = pfnDllGetClassObject (
|
||
|
&CLSID_DirectSoundPrivate,
|
||
|
&IID_IClassFactory,
|
||
|
(LPVOID*)&pClassFactory
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create the DirectSoundPrivate object and query for an IKsPropertySet interface
|
||
|
//
|
||
|
if(SUCCEEDED(hr)) {
|
||
|
hr = pClassFactory->lpVtbl->CreateInstance (
|
||
|
pClassFactory,
|
||
|
NULL,
|
||
|
&IID_IKsPropertySet,
|
||
|
(LPVOID*)&pKsPropertySet
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Release the class factory
|
||
|
if(pClassFactory) {
|
||
|
pClassFactory->lpVtbl->Release (pClassFactory);
|
||
|
}
|
||
|
|
||
|
// Handle final success or failure
|
||
|
if(SUCCEEDED(hr)) {
|
||
|
*ppKsPropertySet = pKsPropertySet;
|
||
|
}
|
||
|
else if(pKsPropertySet) {
|
||
|
IKsPropertySet_Release (pKsPropertySet);
|
||
|
}
|
||
|
|
||
|
return SUCCEEDED (hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMSystemDirectSound (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
#if 0
|
||
|
|
||
|
HINSTANCE LibDsound = NULL;
|
||
|
LPKSPROPERTYSET pKsPropertySet;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
LibDsound = LoadLibrary (S_DSOUNDLIB);
|
||
|
if(LibDsound) {
|
||
|
|
||
|
if (pDirectSoundPrivateCreate (LibDsound, &pKsPropertySet)) {
|
||
|
|
||
|
b = pRestoreWaveDevicesDSSettings (pKsPropertySet);
|
||
|
|
||
|
IKsPropertySet_Release (pKsPropertySet);
|
||
|
}
|
||
|
|
||
|
FreeLibrary (LibDsound);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMSystemCDSettings (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
DWORD Unit, Volume;
|
||
|
HKEY key, keyUnit;
|
||
|
BYTE defDrive[4] = {0,0,0,0};
|
||
|
BYTE defVolume[8] = {0,0,0,0,0,0,0,0};
|
||
|
TCHAR unitKeyStr [MAX_TCHAR_PATH];
|
||
|
LONG rc;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (pRestoreSystemValue (S_CDROM, S_DEFAULTDRIVE, NULL, &Unit)) {
|
||
|
|
||
|
defDrive [0] = (BYTE)Unit;
|
||
|
|
||
|
key = CreateRegKey (HKEY_LOCAL_MACHINE, S_SKEY_CDAUDIO);
|
||
|
if (key) {
|
||
|
|
||
|
rc = RegSetValueEx (key, S_DEFAULTDRIVE, 0, REG_BINARY, defDrive, sizeof(defDrive));
|
||
|
if (rc == ERROR_SUCCESS) {
|
||
|
|
||
|
if (pRestoreSystemValue (S_CDROM, S_VOLUMESETTINGS, NULL, &Volume)) {
|
||
|
|
||
|
wsprintf (unitKeyStr, S_SKEY_CDUNIT, Unit);
|
||
|
|
||
|
keyUnit = CreateRegKey (HKEY_LOCAL_MACHINE, unitKeyStr);
|
||
|
if (keyUnit) {
|
||
|
|
||
|
defVolume [4] = (BYTE)Volume;
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
keyUnit,
|
||
|
S_VOLUMESETTINGS,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
defVolume,
|
||
|
sizeof(defVolume)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
CloseRegKey (keyUnit);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CloseRegKey (key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMSystemMCISoundSettings (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
TCHAR DriverName[MAX_PATH], Param[2];
|
||
|
DWORD Size, Value;
|
||
|
HKEY KeyMCI32;
|
||
|
BOOL b = FALSE;
|
||
|
LONG rc;
|
||
|
|
||
|
rc = TrackedRegOpenKeyEx (HKEY_LOCAL_MACHINE, S_SKEY_WINNT_MCI, 0, KEY_READ, &KeyMCI32);
|
||
|
if (rc == ERROR_SUCCESS) {
|
||
|
|
||
|
Size = sizeof (DriverName);
|
||
|
rc = RegQueryValueEx (KeyMCI32, S_WAVEAUDIO, NULL, NULL, (LPBYTE)DriverName, &Size);
|
||
|
if (rc == ERROR_SUCCESS) {
|
||
|
|
||
|
if (pRestoreSystemValue (S_MCI, S_WAVEAUDIO, NULL, &Value)) {
|
||
|
if (Value >= 2 && Value <= 9) {
|
||
|
|
||
|
wsprintf (Param, TEXT("%lu"), Value);
|
||
|
if (WriteProfileString (DriverName, S_WAVEAUDIO, Param)) {
|
||
|
b = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseRegKey (KeyMCI32);
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreUserValue (
|
||
|
IN PCTSTR KeyName,
|
||
|
IN PCTSTR Field, OPTIONAL
|
||
|
IN PCTSTR StrValue, OPTIONAL
|
||
|
OUT PDWORD NumValue
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreUserValue gets a numeric value from MemDB database,
|
||
|
specific for the current user.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
KeyName - Specifies the name of key
|
||
|
|
||
|
Field - Specifies an optional field
|
||
|
|
||
|
StrValue - Specifies an optional value name
|
||
|
|
||
|
NumValue - Receives the value, if present
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if value was present and read successfully, FALSE if not
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TCHAR Key[MEMDB_MAX];
|
||
|
|
||
|
MemDbBuildKey (Key, g_UserData, KeyName, Field, StrValue);
|
||
|
return MemDbGetValue (Key, NumValue);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserPreferredOnly (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserPreferredOnly restores user's preference to use only
|
||
|
selected devices for playback and record
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HKEY soundMapperKey;
|
||
|
DWORD preferredOnly;
|
||
|
LONG rc;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (pRestoreUserValue (S_AUDIO, S_PREFERREDONLY, NULL, &preferredOnly)) {
|
||
|
|
||
|
soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
|
||
|
if (soundMapperKey != NULL) {
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
soundMapperKey,
|
||
|
S_PREFERREDONLY,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)&preferredOnly,
|
||
|
sizeof (preferredOnly)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
CloseRegKey (soundMapperKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserShowVolume (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserShowVolume restores user's preference to have Volume settings
|
||
|
displayed on the taskbar or not
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HKEY sysTrayKey;
|
||
|
DWORD ShowVolume;
|
||
|
PDWORD Services;
|
||
|
LONG rc;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (pRestoreUserValue (S_AUDIO, S_SHOWVOLUME, NULL, &ShowVolume)) {
|
||
|
|
||
|
sysTrayKey = CreateRegKey (g_UserRoot, S_SKEY_SYSTRAY);
|
||
|
if (sysTrayKey != NULL) {
|
||
|
|
||
|
Services = GetRegValueDword (sysTrayKey, S_SERVICES);
|
||
|
if (Services != NULL) {
|
||
|
|
||
|
if (ShowVolume) {
|
||
|
*Services |= SERVICE_SHOWVOLUME;
|
||
|
} else {
|
||
|
*Services &= ~SERVICE_SHOWVOLUME;
|
||
|
}
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
sysTrayKey,
|
||
|
S_SERVICES,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)Services,
|
||
|
sizeof (*Services)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
MemFreeWrapper (Services);
|
||
|
}
|
||
|
|
||
|
CloseRegKey (sysTrayKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserVideoSettings (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserVideoSettings restores user's preferred Video for Windows settings.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HKEY videoSetKey;
|
||
|
DWORD VideoSettings;
|
||
|
LONG rc;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
if (pRestoreUserValue (S_VIDEO, S_VIDEOSETTINGS, NULL, &VideoSettings)) {
|
||
|
|
||
|
videoSetKey = CreateRegKey (g_UserRoot, S_SKEY_VIDEOUSER);
|
||
|
if (videoSetKey != NULL) {
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
videoSetKey,
|
||
|
S_DEFAULTOPTIONS,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)&VideoSettings,
|
||
|
sizeof (VideoSettings)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
CloseRegKey (videoSetKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserPreferredPlayback (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserPreferredPlayback restores user's preferred playback device.
|
||
|
If the system doesn't have at least 2 wave out devices, nothing is changed.
|
||
|
If there are multiple devices, selection is based on the device ID number,
|
||
|
which is supposed to be left unchanged.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#if 0
|
||
|
|
||
|
HKEY soundMapperKey;
|
||
|
UINT waveOutNumDevs;
|
||
|
DWORD UserPlayback, Value;
|
||
|
WAVEOUTCAPS waveOutCaps;
|
||
|
LONG rc;
|
||
|
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
waveOutNumDevs = waveOutGetNumDevs();
|
||
|
if (!waveOutNumDevs) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserPreferredPlayback: waveOutGetNumDevs returned 0"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (waveOutNumDevs <= 1) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (!pRestoreSystemValue (S_WAVEOUTNUMDEVS, NULL, NULL, &Value) ||
|
||
|
Value != (DWORD)waveOutNumDevs) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (pRestoreUserValue (S_AUDIO, S_PREFERREDPLAY, NULL, &UserPlayback)) {
|
||
|
|
||
|
rc = waveOutGetDevCaps (UserPlayback, &waveOutCaps, sizeof (waveOutCaps));
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
|
||
|
if (soundMapperKey != NULL) {
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
soundMapperKey,
|
||
|
S_PLAYBACK,
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(PCBYTE)waveOutCaps.szPname,
|
||
|
SizeOfString (waveOutCaps.szPname)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
CloseRegKey (soundMapperKey);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserPreferredRecord (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserPreferredRecord restores user's preferred record device.
|
||
|
If the system doesn't have at least 2 wave in devices, nothing is changed.
|
||
|
If there are multiple devices, selection is based on the device ID number,
|
||
|
which is supposed to be left unchanged.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#if 0
|
||
|
|
||
|
HKEY soundMapperKey;
|
||
|
UINT waveInNumDevs;
|
||
|
DWORD UserRecord, Value;
|
||
|
WAVEINCAPS waveInCaps;
|
||
|
LONG rc;
|
||
|
BOOL b = FALSE;
|
||
|
|
||
|
waveInNumDevs = waveInGetNumDevs();
|
||
|
if (!waveInNumDevs) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserPreferredRecord: waveInGetNumDevs returned 0"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (waveInNumDevs <= 1) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (!pRestoreSystemValue (S_WAVEINNUMDEVS, NULL, NULL, &Value) ||
|
||
|
Value != (DWORD)waveInNumDevs) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (pRestoreUserValue (S_AUDIO, S_PREFERREDREC, NULL, &UserRecord)) {
|
||
|
|
||
|
rc = waveInGetDevCaps (UserRecord, &waveInCaps, sizeof (waveInCaps));
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
soundMapperKey = CreateRegKey (g_UserRoot, S_SKEY_SOUNDMAPPER);
|
||
|
if (soundMapperKey != NULL) {
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
soundMapperKey,
|
||
|
S_RECORD,
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(PCBYTE)waveInCaps.szPname,
|
||
|
SizeOfString (waveInCaps.szPname)
|
||
|
);
|
||
|
|
||
|
b = (rc == ERROR_SUCCESS);
|
||
|
|
||
|
CloseRegKey (soundMapperKey);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pRestoreMMUserSndVol32 (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pRestoreMMUserSndVol32 restores SndVol32 options for the current user
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if settings were restored properly
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HKEY Options;
|
||
|
PDWORD Style;
|
||
|
DWORD NewStyle;
|
||
|
BOOL ShowAdvanced;
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
HKEY VolControl, MixerKey;
|
||
|
DWORD Value;
|
||
|
UINT MixerID, MixerMaxID;
|
||
|
MIXERCAPS mixerCaps;
|
||
|
TCHAR MixerNum[MAX_PATH];
|
||
|
LONG rc;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (pRestoreUserValue (S_SNDVOL32, S_SHOWADVANCED, NULL, &ShowAdvanced)) {
|
||
|
|
||
|
Options = CreateRegKey (g_UserRoot, S_SKEY_VOLCTL_OPTIONS);
|
||
|
if (Options != NULL) {
|
||
|
|
||
|
Style = GetRegValueDword (Options, S_STYLE);
|
||
|
if (Style != NULL) {
|
||
|
NewStyle = *Style;
|
||
|
MemFreeWrapper (Style);
|
||
|
} else {
|
||
|
NewStyle = 0;
|
||
|
}
|
||
|
|
||
|
if (ShowAdvanced) {
|
||
|
NewStyle |= STYLE_SHOWADVANCED;
|
||
|
} else {
|
||
|
NewStyle &= ~STYLE_SHOWADVANCED;
|
||
|
}
|
||
|
|
||
|
RegSetValueEx (
|
||
|
Options,
|
||
|
S_STYLE,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)&NewStyle,
|
||
|
sizeof (NewStyle)
|
||
|
);
|
||
|
|
||
|
CloseRegKey (Options);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
//
|
||
|
// restore window position for each mixer device
|
||
|
//
|
||
|
if (!pRestoreSystemValue (S_MIXERNUMDEVS, NULL, NULL, &MixerMaxID)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
MixerID = mixerGetNumDevs ();
|
||
|
if (!MixerID) {
|
||
|
DEBUGMSG ((DBG_MMEDIA, "pRestoreMMUserSndVol32: mixerGetNumDevs returned 0"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (MixerMaxID != MixerID) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
VolControl = CreateRegKey (g_UserRoot, S_SKEY_VOLUMECONTROL);
|
||
|
if (VolControl != NULL) {
|
||
|
|
||
|
for (MixerID = 0; MixerID < MixerMaxID; MixerID++) {
|
||
|
|
||
|
rc = mixerGetDevCaps (MixerID, &mixerCaps, sizeof (MIXERCAPS));
|
||
|
if (rc == MMSYSERR_NOERROR) {
|
||
|
|
||
|
wsprintf (MixerNum, S_MIXERID, MixerID);
|
||
|
|
||
|
MixerKey = CreateRegKey (VolControl, mixerCaps.szPname);
|
||
|
if (MixerKey) {
|
||
|
|
||
|
if (pRestoreUserValue (S_SNDVOL32, MixerNum, S_X, &Value)) {
|
||
|
RegSetValueEx (
|
||
|
MixerKey,
|
||
|
S_X,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)&Value,
|
||
|
sizeof (Value)
|
||
|
);
|
||
|
}
|
||
|
if (pRestoreUserValue (S_SNDVOL32, MixerNum, S_Y, &Value)) {
|
||
|
RegSetValueEx (
|
||
|
MixerKey,
|
||
|
S_Y,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(PCBYTE)&Value,
|
||
|
sizeof (Value)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
CloseRegKey (MixerKey);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseRegKey (VolControl);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pPreserveCurrentSoundScheme (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HKEY Sounds;
|
||
|
LONG rc = E_FAIL;
|
||
|
|
||
|
//
|
||
|
// if WinMM finds HKCU\Control Panel\Sounds [SystemDefault] = ","
|
||
|
// it doesn't override user's current sound scheme
|
||
|
//
|
||
|
Sounds = CreateRegKey (g_UserRoot, S_SKEY_CPANEL_SOUNDS);
|
||
|
if (Sounds != NULL) {
|
||
|
|
||
|
rc = RegSetValueEx (
|
||
|
Sounds,
|
||
|
S_SYSTEMDEFAULT,
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(PCBYTE)S_DUMMYVALUE,
|
||
|
SizeOfString (S_DUMMYVALUE)
|
||
|
);
|
||
|
|
||
|
CloseRegKey (Sounds);
|
||
|
}
|
||
|
|
||
|
return rc == ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define DEFMAC(Item) pRestore##Item,
|
||
|
|
||
|
static MM_SETTING_ACTION g_MMRestoreSystemSettings [] = {
|
||
|
MM_SYSTEM_SETTINGS
|
||
|
};
|
||
|
|
||
|
static MM_SETTING_ACTION g_MMRestoreUserSettings [] = {
|
||
|
MM_USER_SETTINGS
|
||
|
};
|
||
|
|
||
|
#undef DEFMAC
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
RestoreMMSettings_System (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
g_MmediaPool = PoolMemInitNamedPool ("MMediaNT");
|
||
|
if (!g_MmediaPool) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < sizeof (g_MMRestoreSystemSettings) / sizeof (MM_SETTING_ACTION); i++) {
|
||
|
(* g_MMRestoreSystemSettings[i]) ();
|
||
|
}
|
||
|
|
||
|
PoolMemDestroyPool (g_MmediaPool);
|
||
|
g_MmediaPool = NULL;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
RestoreMMSettings_User (
|
||
|
IN PCTSTR UserName,
|
||
|
IN HKEY UserRoot
|
||
|
)
|
||
|
{
|
||
|
INT i;
|
||
|
|
||
|
if (!UserName || UserName[0] == 0) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
MYASSERT (g_UserData == NULL);
|
||
|
g_UserData = JoinPaths (MEMDB_CATEGORY_MMEDIA_USERS, UserName);
|
||
|
g_UserRoot = UserRoot;
|
||
|
|
||
|
__try {
|
||
|
for (i = 0; i < sizeof (g_MMRestoreUserSettings) / sizeof (MM_SETTING_ACTION); i++) {
|
||
|
(* g_MMRestoreUserSettings[i]) ();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// special action to prevent WinMM overriding current sound scheme
|
||
|
//
|
||
|
pPreserveCurrentSoundScheme ();
|
||
|
}
|
||
|
__finally {
|
||
|
FreePathString (g_UserData);
|
||
|
g_UserData = NULL;
|
||
|
g_UserRoot = NULL;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|