mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:33:04 +00:00
Create a branch for header work.
svn path=/branches/header-work/; revision=45691
This commit is contained in:
parent
14fe274b1c
commit
9ea495ba33
19538 changed files with 0 additions and 1063950 deletions
482
lib/drivers/sound/legacy/devname.c
Normal file
482
lib/drivers/sound/legacy/devname.c
Normal file
|
@ -0,0 +1,482 @@
|
|||
/*
|
||||
ReactOS Sound System
|
||||
Device naming & creation helper routines
|
||||
|
||||
Author:
|
||||
Andrew Greenwood (silverblade@reactos.org)
|
||||
|
||||
History:
|
||||
25 May 2008 - Created
|
||||
*/
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <ntddsnd.h>
|
||||
#include <sndnames.h>
|
||||
#include <sndtypes.h>
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/*
|
||||
Default device names
|
||||
|
||||
Just to keep things tidy, we define a structure to hold both the \\Device
|
||||
and \\DosDevices names, and then fill this structure with the default
|
||||
device names that can be found in NTDDSND.H
|
||||
*/
|
||||
|
||||
typedef struct _DEVICE_NAME_GROUP
|
||||
{
|
||||
PCWSTR DeviceName;
|
||||
PCWSTR DosDeviceName;
|
||||
} DEVICE_NAME_GROUP;
|
||||
|
||||
DEVICE_NAME_GROUP SoundDeviceNameBodies[6] =
|
||||
{
|
||||
{
|
||||
DD_WAVE_IN_DEVICE_NAME_U,
|
||||
DD_WAVE_IN_DOS_DEVICE_NAME_U
|
||||
},
|
||||
{
|
||||
DD_WAVE_OUT_DEVICE_NAME_U,
|
||||
DD_WAVE_OUT_DOS_DEVICE_NAME_U
|
||||
},
|
||||
{
|
||||
DD_MIDI_IN_DEVICE_NAME_U,
|
||||
DD_MIDI_IN_DOS_DEVICE_NAME_U
|
||||
},
|
||||
{
|
||||
DD_MIDI_OUT_DEVICE_NAME_U,
|
||||
DD_MIDI_OUT_DOS_DEVICE_NAME_U
|
||||
},
|
||||
{
|
||||
DD_MIX_DEVICE_NAME_U,
|
||||
DD_MIX_DOS_DEVICE_NAME_U
|
||||
},
|
||||
{
|
||||
DD_AUX_DEVICE_NAME_U,
|
||||
DD_AUX_DOS_DEVICE_NAME_U
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
ConstructDeviceName
|
||||
|
||||
This takes a wide-character string containing the device name body (for
|
||||
example, "\\Device\\WaveOut") and appends the device index, forming a
|
||||
string like "\\Device\\WaveOut0", and so on.
|
||||
|
||||
The resulting device name is a unicode string.
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
ConstructDeviceName(
|
||||
IN PCWSTR Path,
|
||||
IN UCHAR Index,
|
||||
OUT PUNICODE_STRING DeviceName)
|
||||
{
|
||||
UNICODE_STRING UnicodePath;
|
||||
UNICODE_STRING UnicodeIndex;
|
||||
WCHAR IndexStringBuffer[5];
|
||||
USHORT Size;
|
||||
USHORT LastCharacterIndex;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! Path ) || ( ! DeviceName ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device index %d out of range", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Initialise the unicode path string */
|
||||
RtlInitUnicodeString(&UnicodePath, Path);
|
||||
|
||||
/* Calculate the length to hold the full string */
|
||||
Size = UnicodePath.Length +
|
||||
sizeof(IndexStringBuffer) +
|
||||
sizeof(UNICODE_NULL);
|
||||
|
||||
/* Allocate memory for DeviceName */
|
||||
DeviceName->Buffer = ExAllocatePool(PagedPool, Size);
|
||||
DeviceName->MaximumLength = Size;
|
||||
|
||||
if ( ! DeviceName->Buffer )
|
||||
{
|
||||
DPRINT("Couldn't allocate memory for device name string");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Copy the path */
|
||||
RtlCopyUnicodeString(DeviceName, &UnicodePath);
|
||||
|
||||
/* Convert Index to string and append */
|
||||
UnicodeIndex.Buffer = IndexStringBuffer;
|
||||
UnicodeIndex.MaximumLength = sizeof(IndexStringBuffer);
|
||||
|
||||
RtlIntegerToUnicodeString((ULONG)Index, 10, &UnicodeIndex);
|
||||
RtlAppendUnicodeStringToString(DeviceName, &UnicodeIndex);
|
||||
|
||||
/* Terminate the string */
|
||||
LastCharacterIndex = DeviceName->Length / sizeof(UNICODE_NULL);
|
||||
DeviceName->Buffer[LastCharacterIndex] = UNICODE_NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
FreeUnicodeStringBuffer
|
||||
|
||||
A small helper routine to free a unicode string buffer, nullify the
|
||||
buffer and reset the lengths to zero.
|
||||
*/
|
||||
|
||||
VOID
|
||||
FreeUnicodeStringBuffer(IN PUNICODE_STRING String)
|
||||
{
|
||||
ASSERT(String != NULL);
|
||||
ASSERT(String->Buffer != NULL);
|
||||
|
||||
ExFreePool(String->Buffer);
|
||||
|
||||
String->Buffer = NULL;
|
||||
String->Length = 0;
|
||||
String->MaximumLength = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
GetDefaultSoundDeviceNameBodies
|
||||
|
||||
Simply accesses the SoundDeviceNameBodies struct defined earlier and
|
||||
fills the DeviceNameBody and DosDeviceNameBody parameters accordingly.
|
||||
|
||||
Basically a "safe" way to access the array and perform two assignments
|
||||
with one call, as this will assign the name and DOS name if a valid
|
||||
DeviceType is passed, otherwise it will fail with STATUS_INVALID_PARAMETER.
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
GetDefaultSoundDeviceNameBodies(
|
||||
IN UCHAR DeviceType,
|
||||
OUT PCWSTR* DeviceNameBody,
|
||||
OUT PCWSTR* DosDeviceNameBody)
|
||||
{
|
||||
if ( ! IS_VALID_SOUND_DEVICE_TYPE(DeviceType) )
|
||||
{
|
||||
DPRINT("Invalid device type");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ( DeviceNameBody )
|
||||
{
|
||||
DPRINT("Reporting device name\n");
|
||||
*DeviceNameBody = SoundDeviceNameBodies[DeviceType].DeviceName;
|
||||
DPRINT("%ws\n", *DeviceNameBody);
|
||||
}
|
||||
|
||||
if ( DosDeviceNameBody )
|
||||
{
|
||||
DPRINT("Reporting DOS device name\n");
|
||||
*DosDeviceNameBody = SoundDeviceNameBodies[DeviceType].DosDeviceName;
|
||||
DPRINT("%ws\n", *DosDeviceNameBody);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ConstructSoundDeviceNames
|
||||
|
||||
Given two wide-character strings and a device index, convert these into
|
||||
two unicode strings with the index appended to the end.
|
||||
|
||||
This is intended for converting a device name and a DOS device name at
|
||||
the same time.
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
ConstructSoundDeviceNames(
|
||||
IN PCWSTR DeviceNameBody,
|
||||
IN PCWSTR DosDeviceNameBody,
|
||||
IN UCHAR Index,
|
||||
OUT PUNICODE_STRING FullDeviceName,
|
||||
OUT PUNICODE_STRING FullDosDeviceName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! DeviceNameBody ) || ( ! DosDeviceNameBody ) ||
|
||||
( ! FullDeviceName ) || ( ! FullDosDeviceName ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device %d exceeds maximum", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConstructDeviceName(DeviceNameBody, Index, FullDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
/* No need to clean up on failure here */
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConstructDeviceName(DosDeviceNameBody, Index, FullDosDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
/* We need to free the string we successfully got earlier */
|
||||
FreeUnicodeStringBuffer(FullDeviceName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CreateSoundDevice
|
||||
|
||||
Creates a device and symbolically-links a DOS device to this. Use this
|
||||
when you want to specify alternative device names to the defaults
|
||||
(eg: "\\Device\\MySoundDev" rather than "\\Device\\WaveOut")
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
CreateSoundDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PCWSTR WideDeviceName,
|
||||
IN PCWSTR WideDosDeviceName,
|
||||
IN UCHAR Index,
|
||||
IN ULONG ExtensionSize,
|
||||
OUT PDEVICE_OBJECT* DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING DosDeviceName;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! DriverObject ) || ( ! DeviceObject ) ||
|
||||
( ! WideDeviceName ) || ( ! WideDosDeviceName ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device index %d exceeds maximum", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Construct the device and DOS device names */
|
||||
Status = ConstructSoundDeviceNames(WideDeviceName,
|
||||
WideDosDeviceName,
|
||||
Index,
|
||||
&DeviceName,
|
||||
&DosDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Creating device %ws\n", DeviceName.Buffer);
|
||||
|
||||
/* Now create the device */
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
ExtensionSize,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_SOUND,
|
||||
0,
|
||||
FALSE,
|
||||
DeviceObject);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
/* These will have been allocated by ConstructSoundDeviceNames */
|
||||
FreeUnicodeStringBuffer(&DeviceName);
|
||||
FreeUnicodeStringBuffer(&DosDeviceName);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Creating link %ws\n", DosDeviceName.Buffer);
|
||||
|
||||
/* Create a symbolic link for the DOS deviec name */
|
||||
Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
IoDeleteDevice(*DeviceObject);
|
||||
|
||||
/* These will have been allocated by ConstructSoundDeviceNames */
|
||||
FreeUnicodeStringBuffer(&DeviceName);
|
||||
FreeUnicodeStringBuffer(&DosDeviceName);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CreateSoundDeviceWithDefaultName
|
||||
|
||||
Similar to CreateSoundDevice, except this uses the default device names
|
||||
("\\Device\\WaveOut" etc.) based on the DeviceType parameter.
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
CreateSoundDeviceWithDefaultName(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN UCHAR DeviceType,
|
||||
IN UCHAR Index,
|
||||
IN ULONG ExtensionSize,
|
||||
OUT PDEVICE_OBJECT* DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCWSTR WideDeviceName = NULL;
|
||||
PCWSTR WideDosDeviceName = NULL;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! DriverObject ) || ( ! DeviceObject ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device index %d exceeds maximum", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Look-up the default name based on the device type */
|
||||
Status = GetDefaultSoundDeviceNameBodies(DeviceType,
|
||||
&WideDeviceName,
|
||||
&WideDosDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Go create the device! */
|
||||
Status = CreateSoundDevice(DriverObject,
|
||||
WideDeviceName,
|
||||
WideDosDeviceName,
|
||||
Index,
|
||||
ExtensionSize,
|
||||
DeviceObject);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
/* No clean-up to do */
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DestroySoundDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCWSTR WideDosDeviceName,
|
||||
IN UCHAR Index)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DosDeviceName;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! WideDosDeviceName ) || ( ! DeviceObject ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device %d exceeds maximum", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConstructDeviceName(WideDosDeviceName, Index, &DosDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Deleting symlink %ws\n", DosDeviceName.Buffer);
|
||||
|
||||
Status = IoDeleteSymbolicLink(&DosDeviceName);
|
||||
DPRINT("Status of symlink deletion is 0x%08x\n", Status);
|
||||
/*
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
*/
|
||||
|
||||
IoDeleteDevice(DeviceObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DestroySoundDeviceWithDefaultName(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR DeviceType,
|
||||
IN UCHAR Index)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCWSTR WideDosDeviceName = NULL;
|
||||
|
||||
/* Check for NULL parameters */
|
||||
if ( ( ! DeviceObject ) )
|
||||
{
|
||||
DPRINT("Unexpected NULL parameter");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Range-check */
|
||||
if ( Index >= SOUND_MAX_DEVICES )
|
||||
{
|
||||
DPRINT("Device index %d exceeds maximum", Index);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Look-up the default name based on the device type */
|
||||
Status = GetDefaultSoundDeviceNameBodies(DeviceType,
|
||||
NULL,
|
||||
&WideDosDeviceName);
|
||||
|
||||
if ( ! NT_SUCCESS(Status) )
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("DOS device name at %p\n", WideDosDeviceName);
|
||||
|
||||
DPRINT("DOS device name is based on %ws\n", WideDosDeviceName);
|
||||
|
||||
return DestroySoundDevice(DeviceObject, WideDosDeviceName, Index);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue