From 26895c3eacf27eb20659afc6cce176e67bbf41ca Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Mon, 1 Nov 2010 22:21:24 +0000 Subject: [PATCH] [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 --- reactos/drivers/ksfilter/ks/irp.c | 33 ++--- .../wdm/audio/backpln/portcls/interrupt.cpp | 8 +- .../wdm/audio/backpln/portcls/irpstream.cpp | 40 +----- .../drivers/wdm/audio/legacy/wdmaud/control.c | 117 ++++++++++++++++-- .../drivers/wdm/audio/legacy/wdmaud/wdmaud.h | 8 ++ 5 files changed, 139 insertions(+), 67 deletions(-) diff --git a/reactos/drivers/ksfilter/ks/irp.c b/reactos/drivers/ksfilter/ks/irp.c index 5ff56c9a0f8..192aae54d52 100644 --- a/reactos/drivers/ksfilter/ks/irp.c +++ b/reactos/drivers/ksfilter/ks/irp.c @@ -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; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp b/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp index af4b0c18cdf..30d78568550 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp @@ -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; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp index fabf862c334..628ea73edb9 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp @@ -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); diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c index cc4824e62bc..ee5d03f32ea 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c @@ -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 */ diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index e29377aa36b..002cf8d0d0a 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -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;