360 lines
7.7 KiB
C++
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);
|
|
}
|