windows-nt/Source/XPSP1/NT/drivers/wdm/audio/sysaudio/registry.cpp
2020-09-26 16:20:57 +08:00

360 lines
7.7 KiB
C++

//---------------------------------------------------------------------------
//
// Module: registry.c
//
// Description:
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// Mike McLaughlin
//
// History: Date Author Comment
//
// To Do: Date Author Comment
//
//@@END_MSINTERNAL
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "common.h"
//===========================================================================
//===========================================================================
NTSTATUS
GetRegistryDefault(
PSHINGLE_INSTANCE pShingleInstance,
PDEVICE_NODE *ppDeviceNode
)
{
#ifdef REGISTRY_PREFERRED_DEVICE
PKEY_VALUE_FULL_INFORMATION pkvfi = NULL;
PDEVICE_NODE pDeviceNode;
PGRAPH_NODE pGraphNode;
PWSTR pwstrString = NULL;
PWSTR pwstrPath = NULL;
HANDLE hkey = NULL;
NTSTATUS Status;
if(pShingleInstance->pcwstrRegistryPath == NULL ||
pShingleInstance->pcwstrRegistryValue == NULL) {
goto exit;
}
Status = OpenRegistryKey(pShingleInstance->pcwstrRegistryPath, &hkey);
if(!NT_SUCCESS(Status)) {
goto exit;
}
Status = QueryRegistryValue(
hkey,
pShingleInstance->pcwstrRegistryValue,
&pkvfi);
if(!NT_SUCCESS(Status)) {
goto exit;
}
if(pkvfi->Type != REG_SZ) {
Trap();
goto exit;
}
FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
Status = pDeviceNode->CreateGraphNodes();
if(!NT_SUCCESS(Status)) {
goto exit;
}
FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
if((pGraphNode->ulFlags ^
pShingleInstance->ulFlags) &
FLAGS_MIXER_TOPOLOGY) {
continue;
}
Status = FindFriendlyName(
pShingleInstance,
ppDeviceNode,
pGraphNode,
(PWSTR)(((PUCHAR)pkvfi) + pkvfi->DataOffset));
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_LIST_ITEM
} END_EACH_LIST_ITEM
exit:
delete pkvfi;
delete pwstrPath;
delete pwstrString;
if(hkey != NULL) {
ZwClose(hkey);
}
#endif
return(STATUS_SUCCESS);
}
#ifdef REGISTRY_PREFERRED_DEVICE // this registry code doesn't work under NT
// and isn't needed any more
ENUMFUNC
FindFriendlyName(
PSHINGLE_INSTANCE pShingleInstance,
PDEVICE_NODE *ppDeviceNode,
PGRAPH_NODE pGraphNode,
PWSTR pwstr
)
{
NTSTATUS Status = STATUS_SUCCESS;
PSTART_NODE pStartNode;
ULONG c;
// if "Use any available device" (registry key == empty string)
if(wcslen(pwstr) == 0) {
if((pGraphNode->ulFlags &
pShingleInstance->ulFlags &
GN_FLAGS_PREFERRED_MASK) == 0) {
Status = STATUS_CONTINUE;
goto exit;
}
*ppDeviceNode = pGraphNode->pDeviceNode;
ASSERT(NT_SUCCESS(Status));
goto exit;
}
c = wcslen(pGraphNode->pDeviceNode->GetFriendlyName());
DPF2(100, "FindFriendlyName: %s c: %d",
pGraphNode->pDeviceNode->DumpName(),
c);
//
// The device name from the registry needs to be limited to 32 characters
// (include NULL) because "pwstr" has been trunicated to this by
// wdmaud.sys (the getcap structure passed back to winmm has this limit).
//
if(c >= MAXPNAMELEN) {
c = MAXPNAMELEN - 1; // c doesn't include the NULL
}
if(wcsncmp(pwstr, pGraphNode->pDeviceNode->GetFriendlyName(), c) == 0) {
*ppDeviceNode = pGraphNode->pDeviceNode;
ASSERT(NT_SUCCESS(Status));
goto exit;
}
if(pShingleInstance ==
apShingleInstance[KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT]) {
Status = STATUS_CONTINUE;
goto exit;
}
FOR_EACH_LIST_ITEM(&pGraphNode->lstStartNode, pStartNode) {
PPIN_INFO pPinInfo;
Assert(pStartNode);
Assert(pStartNode->pPinNode);
pPinInfo = pStartNode->pPinNode->pPinInfo;
Assert(pPinInfo);
if(pPinInfo->pwstrName == NULL) {
continue;
}
if(pPinInfo->pguidName != NULL) {
Trap();
continue;
}
if(pPinInfo->pguidCategory == NULL) {
Trap();
continue;
}
if(!IsEqualGUID(
&KSCATEGORY_WDMAUD_USE_PIN_NAME,
pPinInfo->pguidCategory)) {
continue;
}
if(wcsncmp(
pwstr,
pPinInfo->pwstrName,
wcslen(pPinInfo->pwstrName)) == 0) {
Status = GetRegistryDefault(
apShingleInstance[KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT],
ppDeviceNode);
goto exit;
}
} END_EACH_LIST_ITEM
Status = STATUS_CONTINUE;
exit:
return(Status);
}
#endif
#ifndef UNDER_NT
NTSTATUS
GetRegistryPlaybackRecordFormat(
PWAVEFORMATEX pWaveFormatEx,
BOOL fPlayback
)
{
PKEY_VALUE_FULL_INFORMATION pkvfiFormatName = NULL;
PKEY_VALUE_FULL_INFORMATION pkvfiFormat = NULL;
HANDLE hkeyAudio = NULL;
HANDLE hkeyFormats = NULL;
NTSTATUS Status;
Status = OpenRegistryKey(
REGSTR_PATH_MULTIMEDIA_AUDIO,
&hkeyAudio);
if(!NT_SUCCESS(Status)) {
goto exit;
}
Status = QueryRegistryValue(
hkeyAudio,
fPlayback ?
REGSTR_VAL_DEFAULT_PLAYBACK_FORMAT :
REGSTR_VAL_DEFAULT_RECORD_FORMAT,
&pkvfiFormatName);
if(!NT_SUCCESS(Status)) {
goto exit;
}
if(pkvfiFormatName->Type != REG_SZ) {
Trap();
Status = STATUS_INVALID_DEVICE_REQUEST;
goto exit;
}
Status = OpenRegistryKey(
REGSTR_PATH_MULTIMEDIA_AUDIO_FORMATS,
&hkeyFormats);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = QueryRegistryValue(
hkeyFormats,
(PCWSTR)(((PUCHAR)pkvfiFormatName) + pkvfiFormatName->DataOffset),
&pkvfiFormat);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
if(pkvfiFormat->Type != REG_BINARY) {
Status = STATUS_INVALID_DEVICE_REQUEST;
goto exit;
}
RtlCopyMemory(
pWaveFormatEx,
((PUCHAR)pkvfiFormat) + pkvfiFormat->DataOffset,
min(pkvfiFormat->DataLength, sizeof(WAVEFORMATEX)));
DPF3(90, "GetRegistryPlayBackRecordFormat: SR: %d CH: %d BPS %d",
pWaveFormatEx->nSamplesPerSec,
pWaveFormatEx->nChannels,
pWaveFormatEx->wBitsPerSample);
exit:
if(hkeyAudio != NULL) {
ZwClose(hkeyAudio);
}
if(hkeyFormats != NULL) {
ZwClose(hkeyFormats);
}
delete pkvfiFormatName;
delete pkvfiFormat;
return(Status);
}
#endif
NTSTATUS
OpenRegistryKey(
PCWSTR pcwstr,
PHANDLE pHandle,
HANDLE hRootDir
)
{
UNICODE_STRING UnicodeDeviceString;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&UnicodeDeviceString, pcwstr);
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeDeviceString,
OBJ_CASE_INSENSITIVE,
hRootDir,
NULL);
return(ZwOpenKey(
pHandle,
KEY_READ | KEY_NOTIFY | KEY_WRITE,
&ObjectAttributes));
}
NTSTATUS
QueryRegistryValue(
HANDLE hkey,
PCWSTR pcwstrValueName,
PKEY_VALUE_FULL_INFORMATION *ppkvfi
)
{
UNICODE_STRING ustrValueName;
NTSTATUS Status;
ULONG cbValue;
*ppkvfi = NULL;
RtlInitUnicodeString(&ustrValueName, pcwstrValueName);
Status = ZwQueryValueKey(
hkey,
&ustrValueName,
KeyValueFullInformation,
NULL,
0,
&cbValue);
if(Status != STATUS_BUFFER_OVERFLOW &&
Status != STATUS_BUFFER_TOO_SMALL) {
goto exit;
}
*ppkvfi = (PKEY_VALUE_FULL_INFORMATION)new BYTE[cbValue];
if(*ppkvfi == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
Status = ZwQueryValueKey(
hkey,
&ustrValueName,
KeyValueFullInformation,
*ppkvfi,
cbValue,
&cbValue);
if(!NT_SUCCESS(Status)) {
delete *ppkvfi;
*ppkvfi = NULL;
goto exit;
}
exit:
return(Status);
}