if (!Buffer)
{
- // probe the stream irp
- Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0);
-
- // check for success
- if (!NT_SUCCESS(Status))
+ if (!Irp->MdlAddress)
{
- DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
- return Status;
+ // ioctl from KsStudio
+ // Wdmaud already probes buffers, therefore no need to probe it again
+ // probe the stream irp
+ Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_ALLOWFORMATCHANGE | KSPROBE_SYSTEMADDRESS, 0);
+
+ // check for success
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
+ return Status;
+ }
}
-
// get the stream header
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
PC_ASSERT(Header);
PC_ASSERT(Irp->MdlAddress);
+ DPRINT("Size %u DataUsed %u FrameExtent %u SizeHeader %u\n", Header->Size, Header->DataUsed, Header->FrameExtent, sizeof(KSSTREAM_HEADER));
+
if (Irp->RequestorMode != KernelMode)
{
// use allocated mdl
Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+ PC_ASSERT(Header->Data);
}
}
else
PC_ASSERT(StreamHeader);
// store buffersize
- *BufferSize = StreamHeader->DataUsed - Offset;
+ if (StreamHeader->DataUsed)
+ *BufferSize = StreamHeader->DataUsed - Offset;
+ else
+ *BufferSize = StreamHeader->FrameExtent - Offset;
+
+ PC_ASSERT(*BufferSize);
// store buffer
*Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
CIrpQueue::UpdateMapping(
IN ULONG BytesWritten)
{
- //PIO_STACK_LOCATION IoStack;
PKSSTREAM_HEADER StreamHeader;
+ ULONG Size;
if (!m_Irp)
{
return;
}
-#if 0
- // get current irp stack location
- IoStack = IoGetCurrentIrpStackLocation(m_Irp);
-
// get stream header
- StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
-#else
- // HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)m_Irp->Tail.Overlay.DriverContext[2];
-#endif
// sanity check
// ASSERT(StreamHeader);
// decrement available data counter
m_NumDataAvailable -= BytesWritten;
- if (m_CurrentOffset >= StreamHeader->DataUsed)
+ if (StreamHeader->DataUsed)
+ Size = StreamHeader->DataUsed;
+ else
+ Size = StreamHeader->FrameExtent;
+
+ PC_ASSERT(Size);
+
+ if (m_CurrentOffset >= Size)
{
// irp has been processed completly
m_Irp->IoStatus.Status = STATUS_SUCCESS;
// frame extend contains the original request size, DataUsed contains the real buffer size
//is different when kmixer performs channel conversion, upsampling etc
- m_Irp->IoStatus.Information = StreamHeader->FrameExtent;
+ m_Irp->IoStatus.Information = Size;
- if (m_Irp->RequestorMode == KernelMode)
- {
- // HACK - WDMAUD should pass PKSSTREAM_HEADERs
- ExFreePool(StreamHeader->Data);
- ExFreePool(StreamHeader);
- }
+ PC_ASSERT_IRQL(DISPATCH_LEVEL);
+ MmUnlockPages(m_Irp->MdlAddress);
+ IoFreeMdl(m_Irp->MdlAddress);
+ m_Irp->MdlAddress = NULL;
+ ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
+ m_Irp->AssociatedIrp.SystemBuffer = NULL;
// complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
Irp->IoStatus.Information = StreamHeader->FrameExtent;
- // free stream data, no tag as wdmaud.drv does it atm
- ExFreePool(StreamHeader->Data);
-
// free stream header, no tag as wdmaud.drv allocates it atm
ExFreePool(StreamHeader);
{
InterlockedIncrement((PLONG)&m_TotalPackets);
- DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u Pre %u Post %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
+ DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
m_IrpQueue->AddMapping(NULL, 0, Irp);
{
PCLOSESTREAM_CONTEXT Ctx;
+ DPRINT1("CPortPinWaveCyclic::Close entered\n");
+
if (m_Stream)
{
// allocate a close context
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
- NTSTATUS Status;
- PCONTEXT_WRITE Packet;
- PIRP Irp;
-
- // HACK to be removed
-
- DPRINT("CPortPinWaveCyclic::FastRead entered\n");
-
- Packet = (PCONTEXT_WRITE)Buffer;
-
- Irp = Packet->Irp;
- StatusBlock->Status = STATUS_PENDING;
-
- Status = m_IrpQueue->AddMapping((PUCHAR)Buffer, Length, Irp);
-
- if (!NT_SUCCESS(Status))
- return FALSE;
-
- StatusBlock->Status = STATUS_PENDING;
-
- return TRUE;
+ return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
}
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
- NTSTATUS Status;
- PCONTEXT_WRITE Packet;
- PIRP Irp;
-
- // HACK to be removed
-
- InterlockedIncrement((PLONG)&m_TotalPackets);
-
- DPRINT("CPortPinWaveCyclic::FastWrite entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
-
- Packet = (PCONTEXT_WRITE)Buffer;
- Irp = Packet->Irp;
-
- Status = m_IrpQueue->AddMapping((PUCHAR)Buffer, Length, Irp);
-
- if (!NT_SUCCESS(Status))
- return FALSE;
-
- StatusBlock->Status = STATUS_PENDING;
-
- return TRUE;
+ return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
}
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
- UNIMPLEMENTED
return FALSE;
}
} PCLASS_DEVICE_EXTENSION, *PPCLASS_DEVICE_EXTENSION;
-typedef struct
-{
- KSSTREAM_HEADER Header;
- PIRP Irp;
-}CONTEXT_WRITE, *PCONTEXT_WRITE;
-
typedef struct
{
PVOID Pin;
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ if (!Node->AutomationTable)
+ {
+ // request is out of bounds
+ Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
+
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ if (!Node->AutomationTable)
+ {
+ // request is out of bounds
+ Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
+
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
case IOCTL_GETCONTROLDETAILS:
return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
-
case IOCTL_GETPOS:
case IOCTL_GETDEVID:
case IOCTL_GETVOLUME:
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
}
-NTSTATUS
-NTAPI
-WdmAudWriteCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP LowerIrp,
- IN PVOID Context)
-{
- //PIRP Irp;
- ASSERT(LowerIrp->PendingReturned == FALSE);
- /* get original irp */
- //Irp = (PIRP)Context;
-
- /* save status */
- //Irp->IoStatus.Status = LowerIrp->IoStatus.Status;
- //Irp->IoStatus.Information = LowerIrp->IoStatus.Information;
- /* complete request */
- //IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
- /* return success to free irp */
- return STATUS_SUCCESS;
-}
-
NTSTATUS
NTAPI
-WdmAudWrite(
+WdmAudReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status;
PWDMAUD_DEVICE_INFO DeviceInfo;
- PWDMAUD_CLIENT ClientInfo;
- NTSTATUS Status = STATUS_SUCCESS;
- PUCHAR Buffer;
PFILE_OBJECT FileObject;
+ PIO_STACK_LOCATION IoStack;
+ ULONG Length;
PMDL Mdl;
- //PIRP LowerIrp;
- PCONTEXT_WRITE Packet;
- PVOID SystemBuffer;
- //LARGE_INTEGER Offset;
- IO_STATUS_BLOCK IoStatusBlock;
+ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
- //DPRINT("WdmAudWrite entered\n");
+ /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
+ Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
- if (IoStack->Parameters.Write.Length < sizeof(WDMAUD_DEVICE_INFO))
- {
- /* invalid parameter */
- DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.Write.Length, sizeof(WDMAUD_DEVICE_INFO));
- return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
- }
+ /* sanity check */
+ ASSERT(Irp->UserBuffer);
- DeviceInfo = (PWDMAUD_DEVICE_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress);
+ /* get the length of the request length */
+ Length = IoStack->Parameters.Write.Length;
+ /* store outputbuffer length */
+ IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
- Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice);
- return SetIrpIoStatus(Irp, Status, 0);
- }
+ /* store mdl address */
+ Mdl = Irp->MdlAddress;
+ /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
+ Irp->MdlAddress = NULL;
- //DPRINT("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa);
- if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
- {
- /* invalid parameter */
- DPRINT1("Error: device type not set\n");
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
- }
+ /* check for success */
- if (!IoStack->FileObject)
+ if (IoStack->MajorFunction == IRP_MJ_WRITE)
{
- /* file object parameter */
- DPRINT1("Error: file object is not attached\n");
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
+ /* probe the write stream irp */
+ Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
}
- ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
-
-
- /* setup stream context */
- Packet = (PCONTEXT_WRITE)ExAllocatePool(NonPagedPool, sizeof(CONTEXT_WRITE));
- if (!Packet)
+ else
{
- /* no memory */
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
+ /* probe the read stream irp */
+ Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
}
- Packet->Header.FrameExtent = DeviceInfo->Header.FrameExtent;
- Packet->Header.DataUsed = DeviceInfo->Header.DataUsed;
- Packet->Header.Size = sizeof(KSSTREAM_HEADER);
- Packet->Header.PresentationTime.Numerator = 1;
- Packet->Header.PresentationTime.Denominator = 1;
- Packet->Irp = Irp;
-
- Buffer = ExAllocatePool(NonPagedPool, DeviceInfo->Header.DataUsed);
- if (!Buffer)
- {
- /* no memory */
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
- }
- Packet->Header.Data = Buffer;
+ /* now free the mdl */
+ IoFreeMdl(Mdl);
- Mdl = IoAllocateMdl(DeviceInfo->Header.Data, DeviceInfo->Header.DataUsed, FALSE, FALSE, FALSE);
- if (!Mdl)
+ if (!NT_SUCCESS(Status))
{
- /* no memory */
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
- ExFreePool(Buffer);
- return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
+ DPRINT1("KsProbeStreamIrp failed with Status %x\n", Status);
+ return SetIrpIoStatus(Irp, Status, 0);
}
- _SEH2_TRY
- {
- MmProbeAndLockPages(Mdl, UserMode, IoReadAccess);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Exception, get the error code */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ /* 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 buffer supplied\n");
- ExFreePool(Buffer);
- ExFreePool(Packet);
- IoFreeMdl(Mdl);
- ObDereferenceObject(FileObject);
+ DPRINT1("Invalid pin handle %x\n", DeviceInfo->hDevice);
return SetIrpIoStatus(Irp, Status, 0);
}
- SystemBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority );
- if (!SystemBuffer)
- {
- DPRINT1("Invalid buffer supplied\n");
- ExFreePool(Buffer);
- ExFreePool(Packet);
- IoFreeMdl(Mdl);
- ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
- }
-
- RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->Header.DataUsed);
- MmUnlockPages(Mdl);
- IoFreeMdl(Mdl);
-
-#if 1
- KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, UserMode);
- /* dereference file object */
- ObDereferenceObject(FileObject);
- return IoStatusBlock.Status;
-#else
- Offset.QuadPart = 0L;
-
- /* now build the irp */
- LowerIrp = IoBuildAsynchronousFsdRequest (IRP_MJ_WRITE,
- IoGetRelatedDeviceObject(FileObject),
- Packet,
- sizeof(KSSTREAM_HEADER),
- &Offset,
- NULL);
-
- if (!LowerIrp)
- {
- /* failed to create an associated irp */
- ExFreePool(Buffer);
- ExFreePool(Packet);
- ObDereferenceObject(FileObject);
-
- return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
- }
+ /* skip current irp stack location */
+ IoSkipCurrentIrpStackLocation(Irp);
/* get next stack location */
- IoStack = IoGetNextIrpStackLocation(LowerIrp);
+ IoStack = IoGetNextIrpStackLocation(Irp);
/* attach file object */
IoStack->FileObject = FileObject;
-
- /* set a completion routine */
- IoSetCompletionRoutine(LowerIrp, WdmAudWriteCompletion, (PVOID)Irp, TRUE, TRUE, TRUE);
+ IoStack->Parameters.Write.Length = sizeof(KSSTREAM_HEADER);
+ IoStack->MajorFunction = IRP_MJ_WRITE;
/* mark irp as pending */
- //IoMarkIrpPending(Irp);
- Irp->IoStatus.Information = DeviceInfo->BufferSize;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- DPRINT1("Wrote %u\n", DeviceInfo->BufferSize);
+ IoMarkIrpPending(Irp);
/* call the driver */
- Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), LowerIrp);
+ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
/* dereference file object */
ObDereferenceObject(FileObject);
- return STATUS_SUCCESS;
-#endif
+ return Status;
}
Driver->DriverUnload = WdmAudUnload;
-
Driver->MajorFunction[IRP_MJ_CREATE] = WdmAudCreate;
Driver->MajorFunction[IRP_MJ_CLOSE] = WdmAudClose;
Driver->MajorFunction[IRP_MJ_PNP] = WdmAudPnp;
Driver->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
Driver->MajorFunction[IRP_MJ_CLEANUP] = WdmAudCleanup;
Driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WdmAudDeviceControl;
- Driver->MajorFunction[IRP_MJ_WRITE] = WdmAudWrite;
+ Driver->MajorFunction[IRP_MJ_WRITE] = WdmAudReadWrite;
+ Driver->MajorFunction[IRP_MJ_READ] = WdmAudReadWrite;
Driver->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
return WdmAudInstallDevice(Driver);
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
-typedef struct
-{
- KSSTREAM_HEADER Header;
- PIRP Irp;
-}CONTEXT_WRITE, *PCONTEXT_WRITE;
-
NTSTATUS
NTAPI
OpenWavePin(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+NTSTATUS
+NTAPI
+WdmAudReadWrite(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
NTSTATUS
NTAPI
WdmAudWrite(
IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_WRITE_STREAM; //FIXME
IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
+ ASSERT(Irp->AssociatedIrp.SystemBuffer);
/* now call the driver */
- return IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
+ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
+
+ /* dereference file object */
+ ObDereferenceObject(FileObject);
+
+ return Status;
+
}
NTSTATUS
return STATUS_SUCCESS;
}
-BOOLEAN
-NTAPI
-Pin_fnFastWrite(
- PFILE_OBJECT FileObject,
- PLARGE_INTEGER FileOffset,
- ULONG Length,
- BOOLEAN Wait,
- ULONG LockKey,
- PVOID Buffer,
- PIO_STATUS_BLOCK IoStatus,
- PDEVICE_OBJECT DeviceObject)
-{
- PDISPATCH_CONTEXT Context;
- PFILE_OBJECT RealFileObject;
- NTSTATUS Status;
-
- DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
-
- Context = (PDISPATCH_CONTEXT)FileObject->FsContext;
-
- if (Context->hMixerPin)
- {
- Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
- if (NT_SUCCESS(Status))
- {
- Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
- ObDereferenceObject(RealFileObject);
- }
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Mixing stream failed with %lx\n", Status);
- DbgBreakPoint();
- return FALSE;
- }
- }
-
- Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
- if (!NT_SUCCESS(Status))
- return FALSE;
-
- Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
-
- ObDereferenceObject(RealFileObject);
-
- if (NT_SUCCESS(Status))
- return TRUE;
- else
- return FALSE;
-}
-
static KSDISPATCH_TABLE PinTable =
{
Pin_fnDeviceIoControl,
KsDispatchInvalidDeviceRequest,
KsDispatchFastIoDeviceControlFailure,
KsDispatchFastReadFailure,
- Pin_fnFastWrite,
+ KsDispatchFastWriteFailure,
};
NTSTATUS