[PORTCLS]

- Portcls does not need to set the size of the audio buffer for completed irps. This is done in a completion callback in wdmaud. Verified with WinXP portcls
[WDMAUD_KERNEL]
- Free allocated mdls in the io completion routine. Also free the associated stream header.
[KS]
- Replace all ms portcls hacks by one. 
- MS Portcls is now working in ReactOS (which is nice for testing audio related bugs) 

svn path=/trunk/; revision=49417
This commit is contained in:
Johannes Anderwald 2010-11-01 22:21:24 +00:00
parent a6e4c15192
commit 26895c3eac
5 changed files with 139 additions and 67 deletions

View file

@ -898,10 +898,6 @@ ProbeMdl:
goto ProbeMdl;
}
#if 0
// HACK for MS PORTCLS
HeaderSize = Length;
#endif
/* probe user mode buffers */
if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
{
@ -1370,7 +1366,7 @@ KsRemoveIrpFromCancelableQueue(
PLIST_ENTRY CurEntry;
KIRQL OldIrql;
//DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
/* check parameters */
if (!QueueHead || !SpinLock)
@ -1629,19 +1625,32 @@ KsAddIrpToCancelableQueue(
PIO_STACK_LOCATION IoStack;
KIRQL OldLevel;
DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
/* check for required parameters */
if (!QueueHead || !SpinLock || !Irp)
return;
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
// HACK for ms portcls
if (IoStack->MajorFunction == IRP_MJ_CREATE)
{
// complete the request
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
if (!DriverCancel)
{
/* default to KsCancelRoutine */
DriverCancel = KsCancelRoutine;
}
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* acquire spinlock */
KeAcquireSpinLock(SpinLock, &OldLevel);
@ -1973,12 +1982,6 @@ KsSetMajorFunctionHandler(
IN ULONG MajorFunction)
{
DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
#if 1
// HACK
// for MS PORTCLS
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate;
#endif
switch ( MajorFunction )
{
@ -2016,7 +2019,7 @@ KsDispatchIrp(
PKSIDEVICE_HEADER DeviceHeader;
PDEVICE_EXTENSION DeviceExtension;
//DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

View file

@ -232,21 +232,21 @@ CInterruptSync::Connect()
if (IsListEmpty(&m_ServiceRoutines))
return STATUS_UNSUCCESSFUL;
DPRINT("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity);
DPRINT1("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity);
Status = IoConnectInterrupt(&m_Interrupt,
IInterruptServiceRoutine,
(PVOID)this,
&m_Lock,
NULL, //&m_Lock,
Descriptor->u.Interrupt.Vector,
(KIRQL)Descriptor->u.Interrupt.Level,
(KIRQL)Descriptor->u.Interrupt.Level,
(KINTERRUPT_MODE)(Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
(Descriptor->Flags != CM_RESOURCE_INTERRUPT_LATCHED),
(Descriptor->ShareDisposition != CmResourceShareDeviceExclusive),
Descriptor->u.Interrupt.Affinity,
FALSE);
DPRINT("CInterruptSync::Connect result %x\n", Status);
DPRINT1("CInterruptSync::Connect result %x\n", Status);
return Status;
}

View file

@ -293,7 +293,6 @@ CIrpQueue::UpdateMapping(
{
PKSSTREAM_HEADER StreamHeader;
ULONG Size, NumData, Index;
//PMDL CurMdl, NextMdl;
if (!m_Irp)
{
@ -340,8 +339,7 @@ CIrpQueue::UpdateMapping(
return;
}
// irp has been processed completly
// irp has been processed completly
NumData = 0;
if (m_Irp->RequestorMode == KernelMode)
StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer;
@ -385,44 +383,10 @@ CIrpQueue::UpdateMapping(
// done
return;
}
#if 0
// now free allocated mdls
CurMdl = m_Irp->MdlAddress;
for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
{
// sanity check
ASSERT(CurMdl);
// get next mdl
NextMdl = CurMdl->Next;
// check if mdl is locked
if (CurMdl->MdlFlags & MDL_PAGES_LOCKED)
{
// unlock pages
MmUnlockPages(CurMdl);
}
// free mdl
IoFreeMdl(CurMdl);
// proceed to next mdl
CurMdl = NextMdl;
}
// all mdls have been freed now
m_Irp->MdlAddress = NULL;
// free allocated KSSTREAM_HEADER
ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
// is this really needed?
m_Irp->AssociatedIrp.SystemBuffer = NULL;
#endif
// store operation status
m_Irp->IoStatus.Status = STATUS_SUCCESS;
m_Irp->IoStatus.Information = NumData;
m_Irp->IoStatus.Information = 0;
// complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);

View file

@ -384,6 +384,91 @@ WdmAudDeviceControl(
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
}
NTSTATUS
NTAPI
IoCompletion (
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Ctx)
{
PKSSTREAM_HEADER Header;
ULONG Length = 0;
PMDL Mdl, NextMdl;
PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx;
/* get stream header */
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
/* sanity check */
ASSERT(Header);
/* iterate through all stream headers and collect size */
do
{
if (Context->Function == IOCTL_KS_READ_STREAM)
{
/* length is stored in DataUsed */
Length += Header->DataUsed;
}
else
{
/* length stored in frameextend */
Length += Header->FrameExtent;
}
/* subtract size */
Context->Length -= Header->Size;
/* move to next stream header */
Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
}while(Context->Length);
/* 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;
}
/* clear mdl list */
Irp->MdlAddress = NULL;
/* check if mdl is locked */
if (Context->Mdl->MdlFlags & MDL_PAGES_LOCKED)
{
/* unlock pages */
MmUnlockPages(Context->Mdl);
}
/* now free the mdl */
IoFreeMdl(Context->Mdl);
/* now free the stream header */
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information, Length);
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
/* store the length */
Irp->IoStatus.Information = Length;
}
/* free context */
FreeItem(Context);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
@ -398,6 +483,20 @@ WdmAudReadWrite(
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);
@ -414,6 +513,11 @@ WdmAudReadWrite(
/* 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;
@ -441,16 +545,6 @@ WdmAudReadWrite(
return SetIrpIoStatus(Irp, Status, 0);
}
/* check if mdl is locked */
if (Mdl->MdlFlags & MDL_PAGES_LOCKED)
{
/* unlock pages */
MmUnlockPages(Mdl);
}
/* now free the mdl */
IoFreeMdl(Mdl);
/* get device info */
DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
ASSERT(DeviceInfo);
@ -483,6 +577,9 @@ WdmAudReadWrite(
IoStack->Parameters.Write.Length = Length;
IoStack->MajorFunction = IRP_MJ_WRITE;
IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
/* mark irp as pending */
// IoMarkIrpPending(Irp);
/* call the driver */

View file

@ -16,6 +16,14 @@
#include "interface.h"
typedef struct
{
PMDL Mdl;
ULONG Length;
ULONG Function;
}WDMAUD_COMPLETION_CONTEXT, *PWDMAUD_COMPLETION_CONTEXT;
typedef struct
{
HANDLE Handle;