NT4/private/ntos/dd/sound/soundlib/registry.c
2020-09-30 17:12:29 +02:00

325 lines
7.6 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
registry.c
Abstract:
This module contains common code for Sound Kernel mode device
drivers for accessing the registry
The registry for a sound driver (after recent redesign) is :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<DriverName> :
Device0 ... - one key per card (key name is anachronism but one
can just enumerate the keys which one should anyway
because holes can develop if cards are removed.
Can contain values like 'Interrupt', 'MixerState' etc which
are retained over system boots.
LoadInfo Volatile key - contains info deduced on load
Valuename : Configuration Type: REG_BINARY
Valuename : DeviceName Type: REG_SZ
Valuename : LoadStatus Type: REG_DWORD
Author:
Robin Speed (robinsp) 21-September-1993
Environment:
Kernel mode
Revision History:
--*/
#include <soundlib.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SoundOpenDevicesKey)
#pragma alloc_text(PAGE, SoundEnumSubkeys)
#endif
NTSTATUS
SoundOpenDevicesKey(
IN PWSTR RegistryPathName,
OUT PHANDLE DevicesKey
)
/*++
Routine Description :
Create a volatile key under this driver's services node to contain the
device name list.
Arguments :
RegistryPathName - where our registry entry is
DevicesKey - key to devices key in registry
Return Value :
NT status code - STATUS_SUCCESS if no problems
--*/
{
HANDLE hKey;
HANDLE hSubkey;
OBJECT_ATTRIBUTES oa;
NTSTATUS Status;
UNICODE_STRING DeviceName;
UNICODE_STRING uStr;
RtlInitUnicodeString(&uStr, RegistryPathName);
/*
** First try opening this key
*/
InitializeObjectAttributes(&oa,
&uStr,
OBJ_CASE_INSENSITIVE,
NULL,
(PSECURITY_DESCRIPTOR)NULL);
Status = ZwOpenKey(&hKey,
KEY_CREATE_SUB_KEY,
&oa);
if (!NT_SUCCESS(Status)) {
return Status;
}
RtlInitUnicodeString(&uStr, SOUND_DEVICES_SUBKEY);
InitializeObjectAttributes(&oa,
&uStr,
OBJ_CASE_INSENSITIVE,
hKey,
(PSECURITY_DESCRIPTOR)NULL);
Status = ZwCreateKey(DevicesKey,
KEY_ALL_ACCESS,
&oa,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ZwClose(hKey);
return Status;
}
NTSTATUS
SoundEnumSubkeys(
IN PUNICODE_STRING RegistryPathName,
IN PWSTR Subkey,
IN PSOUND_REGISTRY_CALLBACK_ROUTINE Callback,
IN PVOID Context
)
/*++
Routine Description :
Enumerate the subkeys in the registry entry, calling our routine for
each one.
Arguments :
RegistryPathName - where our registry entry is
Return Value :
NT status code - STATUS_SUCCESS if no problems
--*/
{
HANDLE hKey;
HANDLE hSubkey;
OBJECT_ATTRIBUTES oa;
NTSTATUS Status;
ULONG Index;
UNICODE_STRING SubkeyName;
/*
** First try opening this key
*/
InitializeObjectAttributes(&oa,
RegistryPathName,
OBJ_CASE_INSENSITIVE,
NULL,
(PSECURITY_DESCRIPTOR)NULL);
Status = ZwOpenKey(&hKey,
KEY_READ,
&oa);
if (!NT_SUCCESS(Status)) {
return Status;
}
RtlInitUnicodeString(&SubkeyName, Subkey);
InitializeObjectAttributes(&oa,
&SubkeyName,
OBJ_CASE_INSENSITIVE,
hKey,
(PSECURITY_DESCRIPTOR)NULL);
Status = ZwOpenKey(&hSubkey,
KEY_ENUMERATE_SUB_KEYS,
&oa);
ZwClose(hKey);
if (!NT_SUCCESS(Status)) {
return Status;
}
/*
** Now enumerate the subkeys - calling the callback function for
** each one found
*/
for (Index = 0; ; Index++) {
KEY_BASIC_INFORMATION Info;
PKEY_BASIC_INFORMATION pInfo;
ULONG ResultLength;
ULONG Size;
PWSTR Position;
PWSTR FullName;
/*
** First find the length of the subkey data
*/
Status = ZwEnumerateKey(hSubkey,
Index,
KeyBasicInformation,
&Info,
sizeof(Info),
&ResultLength);
if (Status == STATUS_NO_MORE_ENTRIES || NT_ERROR(Status)) {
break;
}
Size = Info.NameLength + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
pInfo = (PKEY_BASIC_INFORMATION)
ExAllocatePool(PagedPool, Size);
if (pInfo == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = ZwEnumerateKey(hSubkey,
Index,
KeyBasicInformation,
pInfo,
Size,
&ResultLength);
if (!NT_SUCCESS(Status)) {
ExFreePool((PVOID)pInfo);
break;
}
if (Size != ResultLength) {
ExFreePool((PVOID)pInfo);
Status = STATUS_INTERNAL_ERROR;
break;
}
/*
** Generate the fully expanded name and call the callback.
** It is the responsibility of the callback routine to free
** this ultimately (usually on driver unload).
*/
FullName = ExAllocatePool(PagedPool,
RegistryPathName->Length +
sizeof(WCHAR) + // '\'
SubkeyName.Length +
sizeof(WCHAR) + // '\'
pInfo->NameLength + sizeof(UNICODE_NULL));
if (FullName == NULL) {
ExFreePool((PVOID)pInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory((PVOID)FullName,
(PVOID)RegistryPathName->Buffer,
RegistryPathName->Length);
Position = FullName + RegistryPathName->Length / sizeof(WCHAR);
Position[0] = '\\';
Position++;
RtlCopyMemory((PVOID)Position,
(PVOID)Subkey,
SubkeyName.Length);
Position += SubkeyName.Length / sizeof(WCHAR);
Position[0] = '\\';
Position++;
RtlCopyMemory((PVOID)Position,
(PVOID)pInfo->Name,
pInfo->NameLength);
Position += pInfo->NameLength / sizeof(WCHAR);
/*
** Null terminate
*/
Position[0] = UNICODE_NULL;
ExFreePool((PVOID)pInfo);
/*
** Call back with key information
*/
Status = (*Callback)(FullName, Context);
if (!NT_SUCCESS(Status)) {
break;
}
}
ZwClose(hSubkey);
/*
** Don't allow 0 devices
*/
if (Index == 0 && Status == STATUS_NO_MORE_ENTRIES) {
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
return Status == STATUS_NO_MORE_ENTRIES ? STATUS_SUCCESS : Status;
}