mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 04:11:30 +00:00
544 lines
17 KiB
C
544 lines
17 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel Streaming
|
|
* FILE: drivers/wdm/audio/legacy/wdmaud/deviface.c
|
|
* PURPOSE: System Audio graph builder
|
|
* PROGRAMMER: Andrew Greenwood
|
|
* Johannes Anderwald
|
|
*/
|
|
|
|
#include "wdmaud.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
|
|
|
|
NTSTATUS
|
|
WdmAudControlOpen(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
|
{
|
|
return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
}
|
|
|
|
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
|
{
|
|
return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
}
|
|
|
|
if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
|
|
{
|
|
return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
}
|
|
|
|
|
|
return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
WdmAudControlDeviceType(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
ULONG Result = 0;
|
|
|
|
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
|
{
|
|
Result = WdmAudGetMixerDeviceCount();
|
|
}
|
|
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
|
{
|
|
Result = WdmAudGetWaveOutDeviceCount();
|
|
}
|
|
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
|
{
|
|
Result = WdmAudGetWaveInDeviceCount();
|
|
}
|
|
else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
|
|
{
|
|
Result = WdmAudGetMidiInDeviceCount();
|
|
}
|
|
else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
|
|
{
|
|
Result = WdmAudGetMidiOutDeviceCount();
|
|
}
|
|
|
|
|
|
/* store result count */
|
|
DeviceInfo->DeviceCount = Result;
|
|
|
|
DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceCount);
|
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
WdmAudControlDeviceState(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
KSPROPERTY Property;
|
|
KSSTATE State;
|
|
NTSTATUS Status;
|
|
ULONG BytesReturned;
|
|
PFILE_OBJECT FileObject;
|
|
|
|
DPRINT("WdmAudControlDeviceState\n");
|
|
|
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
|
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
}
|
|
|
|
Property.Set = KSPROPSETID_Connection;
|
|
Property.Id = KSPROPERTY_CONNECTION_STATE;
|
|
Property.Flags = KSPROPERTY_TYPE_SET;
|
|
|
|
State = DeviceInfo->u.State;
|
|
|
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
DPRINT("WdmAudControlDeviceState Status %x\n", Status);
|
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
WdmAudCapabilities(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
|
|
DPRINT("WdmAudCapabilities entered\n");
|
|
|
|
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
|
{
|
|
Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
|
|
}
|
|
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
|
{
|
|
Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
|
|
}
|
|
else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
|
|
{
|
|
Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
|
|
}
|
|
|
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudIoctlClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
ULONG Index;
|
|
|
|
for(Index = 0; Index < ClientInfo->NumPins; Index++)
|
|
{
|
|
if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE)
|
|
{
|
|
DPRINT1("Closing device %p\n", DeviceInfo->hDevice);
|
|
ZwClose(DeviceInfo->hDevice);
|
|
ClientInfo->hPins[Index].Handle = NULL;
|
|
SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
|
|
{
|
|
DPRINT1("Closing mixer %p\n", DeviceInfo->hDevice);
|
|
return WdmAudControlCloseMixer(DeviceObject, Irp, DeviceInfo, ClientInfo, Index);
|
|
}
|
|
}
|
|
|
|
SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudFrameSize(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
|
IN PWDMAUD_CLIENT ClientInfo)
|
|
{
|
|
PFILE_OBJECT FileObject;
|
|
KSPROPERTY Property;
|
|
ULONG BytesReturned;
|
|
KSALLOCATOR_FRAMING Framing;
|
|
NTSTATUS Status;
|
|
|
|
/* Get sysaudio pin file object */
|
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
|
|
return SetIrpIoStatus(Irp, Status, 0);
|
|
}
|
|
|
|
/* Setup get framing request */
|
|
Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
|
|
Property.Flags = KSPROPERTY_TYPE_GET;
|
|
Property.Set = KSPROPSETID_Connection;
|
|
|
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
|
|
/* Did we succeed */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Store framesize */
|
|
DeviceInfo->u.FrameSize = Framing.FrameSize;
|
|
}
|
|
|
|
/* Release file object */
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudGetDeviceInterface(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo)
|
|
{
|
|
NTSTATUS Status;
|
|
LPWSTR Device;
|
|
ULONG Size, Length;
|
|
|
|
/* get device interface string input length */
|
|
Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
|
|
|
|
/* get mixer info */
|
|
Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
|
|
|
|
/* check for success */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* invalid device id */
|
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
/* calculate length */
|
|
Length = (wcslen(Device)+1) * sizeof(WCHAR);
|
|
|
|
if (!Size)
|
|
{
|
|
/* store device interface size */
|
|
DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
|
|
}
|
|
else if (Size < Length)
|
|
{
|
|
/* buffer too small */
|
|
DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
|
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
else
|
|
{
|
|
//FIXME SEH
|
|
RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
|
|
}
|
|
|
|
FreeItem(Device);
|
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudResetStream(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PWDMAUD_DEVICE_INFO DeviceInfo)
|
|
{
|
|
KSRESET ResetStream;
|
|
NTSTATUS Status;
|
|
ULONG BytesReturned;
|
|
PFILE_OBJECT FileObject;
|
|
|
|
DPRINT("WdmAudResetStream\n");
|
|
|
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
|
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
}
|
|
|
|
ResetStream = DeviceInfo->u.ResetStream;
|
|
ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END);
|
|
|
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned);
|
|
|
|
ObDereferenceObject(FileObject);
|
|
|
|
DPRINT("WdmAudResetStream Status %x\n", Status);
|
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PWDMAUD_DEVICE_INFO DeviceInfo;
|
|
PWDMAUD_CLIENT ClientInfo;
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DPRINT("WdmAudDeviceControl entered\n");
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
|
|
{
|
|
/* invalid parameter */
|
|
DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO));
|
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
}
|
|
|
|
DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
|
|
{
|
|
/* invalid parameter */
|
|
DPRINT1("Error: device type not set\n");
|
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
}
|
|
|
|
if (!IoStack->FileObject || !IoStack->FileObject->FsContext)
|
|
{
|
|
/* file object parameter */
|
|
DPRINT1("Error: file object is not attached\n");
|
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
}
|
|
ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
|
|
|
|
DPRINT("WdmAudDeviceControl entered\n");
|
|
|
|
switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_OPEN_WDMAUD:
|
|
return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETNUMDEVS_TYPE:
|
|
return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_SETDEVICE_STATE:
|
|
return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETCAPABILITIES:
|
|
return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_CLOSE_WDMAUD:
|
|
return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETFRAMESIZE:
|
|
return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETLINEINFO:
|
|
return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETLINECONTROLS:
|
|
return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_SETCONTROLDETAILS:
|
|
return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_GETCONTROLDETAILS:
|
|
return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_QUERYDEVICEINTERFACESTRING:
|
|
return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
|
|
case IOCTL_GET_MIXER_EVENT:
|
|
return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
|
case IOCTL_RESET_STREAM:
|
|
return WdmAudResetStream(DeviceObject, Irp, DeviceInfo);
|
|
case IOCTL_GETPOS:
|
|
case IOCTL_GETDEVID:
|
|
case IOCTL_GETVOLUME:
|
|
case IOCTL_SETVOLUME:
|
|
|
|
DPRINT1("Unhandled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
|
break;
|
|
}
|
|
|
|
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
IoCompletion (
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp,
|
|
PVOID Ctx)
|
|
{
|
|
PKSSTREAM_HEADER Header;
|
|
PMDL Mdl, NextMdl;
|
|
PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx;
|
|
|
|
/* get stream header */
|
|
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
/* sanity check */
|
|
ASSERT(Header);
|
|
|
|
/* time to free all allocated mdls */
|
|
Mdl = Irp->MdlAddress;
|
|
|
|
while(Mdl)
|
|
{
|
|
/* get next mdl */
|
|
NextMdl = Mdl->Next;
|
|
|
|
/* unlock pages */
|
|
MmUnlockPages(Mdl);
|
|
|
|
/* grab next mdl */
|
|
Mdl = NextMdl;
|
|
}
|
|
//IoFreeMdl(Mdl);
|
|
/* clear mdl list */
|
|
Irp->MdlAddress = Context->Mdl;
|
|
|
|
|
|
|
|
DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
|
|
|
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
|
{
|
|
/* failed */
|
|
Irp->IoStatus.Information = 0;
|
|
}
|
|
|
|
/* dereference file object */
|
|
ObDereferenceObject(Context->FileObject);
|
|
|
|
/* free context */
|
|
FreeItem(Context);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
WdmAudReadWrite(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
PWDMAUD_DEVICE_INFO DeviceInfo;
|
|
PFILE_OBJECT FileObject;
|
|
PIO_STACK_LOCATION IoStack;
|
|
ULONG Length;
|
|
PMDL Mdl;
|
|
BOOLEAN Read = TRUE;
|
|
PWDMAUD_COMPLETION_CONTEXT Context;
|
|
|
|
/* allocate completion context */
|
|
Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT));
|
|
|
|
if (!Context)
|
|
{
|
|
/* not enough memory */
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
/* done */
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* get current irp stack location */
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
|
|
Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
|
|
|
/* sanity check */
|
|
ASSERT(Irp->UserBuffer);
|
|
|
|
/* get the length of the request length */
|
|
Length = IoStack->Parameters.Write.Length;
|
|
|
|
/* store outputbuffer length */
|
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
|
|
|
|
/* setup context */
|
|
Context->Length = Length;
|
|
Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
|
|
Context->Mdl = Irp->MdlAddress;
|
|
|
|
/* store mdl address */
|
|
Mdl = Irp->MdlAddress;
|
|
|
|
/* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */
|
|
Irp->MdlAddress = NULL;
|
|
|
|
if (IoStack->MajorFunction == IRP_MJ_WRITE)
|
|
{
|
|
/* probe the write stream irp */
|
|
Read = FALSE;
|
|
Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
|
|
}
|
|
else
|
|
{
|
|
/* probe the read stream irp */
|
|
Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
|
|
Irp->MdlAddress = Mdl;
|
|
FreeItem(Context);
|
|
return SetIrpIoStatus(Irp, Status, 0);
|
|
}
|
|
|
|
/* get device info */
|
|
DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
ASSERT(DeviceInfo);
|
|
|
|
/* now get sysaudio file object */
|
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
|
|
Irp->MdlAddress = Mdl;
|
|
FreeItem(Context);
|
|
return SetIrpIoStatus(Irp, Status, 0);
|
|
}
|
|
|
|
/* store file object whose reference is released in the completion callback */
|
|
Context->FileObject = FileObject;
|
|
|
|
/* skip current irp stack location */
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
/* get next stack location */
|
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
/* prepare stack location */
|
|
IoStack->FileObject = FileObject;
|
|
IoStack->Parameters.Write.Length = Length;
|
|
IoStack->MajorFunction = IRP_MJ_WRITE;
|
|
IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
|
|
IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
|
|
|
|
/* mark irp as pending */
|
|
// IoMarkIrpPending(Irp);
|
|
/* call the driver */
|
|
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
|
|
return Status;
|
|
}
|