Author: janderwald Date: Mon Nov 1 22:21:24 2010 New Revision: 49417
URL: http://svn.reactos.org/svn/reactos?rev=49417&view=rev Log: [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)
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/irp.c?r... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] Mon Nov 1 22:21:24 2010 @@ -898,10 +898,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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;
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.cpp [iso-8859-1] Mon Nov 1 22:21:24 2010 @@ -232,21 +232,21 @@ 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; }
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] Mon Nov 1 22:21:24 2010 @@ -293,7 +293,6 @@ { PKSSTREAM_HEADER StreamHeader; ULONG Size, NumData, Index; - //PMDL CurMdl, NextMdl;
if (!m_Irp) { @@ -340,8 +339,7 @@ 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 @@ // 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);
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Mon Nov 1 22:21:24 2010 @@ -384,6 +384,91 @@ 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 @@ 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); @@ -413,6 +512,11 @@
/* 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; @@ -440,16 +544,6 @@ Irp->MdlAddress = Mdl; 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; @@ -483,6 +577,9 @@ 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 */
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Mon Nov 1 22:21:24 2010 @@ -18,6 +18,14 @@
typedef struct { + PMDL Mdl; + ULONG Length; + ULONG Function; +}WDMAUD_COMPLETION_CONTEXT, *PWDMAUD_COMPLETION_CONTEXT; + + +typedef struct +{ HANDLE Handle; SOUND_DEVICE_TYPE Type; ULONG FilterId;