mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 22:12:59 +00:00
[KS]
- Implement KsQueryInformationFile - Properly implement KsStreamIo - Fix a desastreous bug in KsRemoveIrpFromCancelableQueue - Implement KsMoveIrpsOnCancelableQueue [PORTCLS] - Switch portcls to use the provided ks irp queue function instead of the homegrown IRP_MAPPING routines. Irp queueing is now faster and consumes less memory - Return an allocated silence buffer when there are no mappings available - HACK-Remove: Don't pre-complete any audio buffers now anymore. If you experience audio stuttering, let me know [SYSAUDIO, PORTCLS, KMIXER] - FastRead / FastWrite routines must store their return values in the status block as KsStreamIo now checks these svn path=/trunk/; revision=42334
This commit is contained in:
parent
47f744578f
commit
9061b8ee40
11 changed files with 468 additions and 280 deletions
|
@ -344,7 +344,7 @@ KsWriteFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@unimplemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
KSDDKAPI
|
KSDDKAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -357,7 +357,13 @@ KsQueryInformationFile(
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PFAST_IO_DISPATCH FastIoDispatch;
|
PFAST_IO_DISPATCH FastIoDispatch;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
KEVENT Event;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
IO_STATUS_BLOCK StatusBlock;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* get related file object */
|
/* get related file object */
|
||||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
@ -386,10 +392,47 @@ KsQueryInformationFile(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* clear event */
|
||||||
|
KeClearEvent(&FileObject->Event);
|
||||||
|
|
||||||
/* Implement Me */
|
/* initialize event */
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
/* set offset to zero */
|
||||||
|
Offset.QuadPart = 0L;
|
||||||
|
|
||||||
|
/* build the request */
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &StatusBlock);
|
||||||
|
|
||||||
|
if (!Irp)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* get next stack location */
|
||||||
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* setup parameters */
|
||||||
|
IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
|
||||||
|
IoStack->Parameters.QueryFile.Length = Length;
|
||||||
|
Irp->AssociatedIrp.SystemBuffer = FileInformation;
|
||||||
|
|
||||||
|
|
||||||
|
/* call the driver */
|
||||||
|
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
|
||||||
|
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* wait for the operation to complete */
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
|
||||||
|
/* is object sync */
|
||||||
|
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||||
|
Status = FileObject->FinalStatus;
|
||||||
|
else
|
||||||
|
Status = StatusBlock.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -506,78 +549,105 @@ KsStreamIo(
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
ULONG Code;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PKSIOBJECT_HEADER ObjectHeader;
|
PKSIOBJECT_HEADER ObjectHeader;
|
||||||
|
BOOLEAN Ret;
|
||||||
|
|
||||||
|
/* get related device object */
|
||||||
if (Flags == KSSTREAM_READ)
|
|
||||||
Code = IRP_MJ_READ;
|
|
||||||
else if (Flags == KSSTREAM_WRITE)
|
|
||||||
Code = IRP_MJ_WRITE;
|
|
||||||
else
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
if (!DeviceObject)
|
/* sanity check */
|
||||||
return STATUS_INVALID_PARAMETER;
|
ASSERT(DeviceObject != NULL);
|
||||||
|
|
||||||
|
/* is there a event provided */
|
||||||
if (Event)
|
if (Event)
|
||||||
{
|
{
|
||||||
KeResetEvent(Event);
|
/* reset event */
|
||||||
|
KeClearEvent(Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ASSERT(DeviceObject->DeviceType == FILE_DEVICE_KS);
|
if (RequestorMode || ExGetPreviousMode() == KernelMode)
|
||||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
|
||||||
ASSERT(ObjectHeader);
|
|
||||||
if (Code == IRP_MJ_READ)
|
|
||||||
{
|
{
|
||||||
|
/* requestor is from kernel land */
|
||||||
|
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||||
|
|
||||||
|
if (ObjectHeader)
|
||||||
|
{
|
||||||
|
/* there is a object header */
|
||||||
|
if (Flags == KSSTREAM_READ)
|
||||||
|
{
|
||||||
|
/* is fast read supported */
|
||||||
if (ObjectHeader->DispatchTable.FastRead)
|
if (ObjectHeader->DispatchTable.FastRead)
|
||||||
{
|
{
|
||||||
if (ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
|
/* call fast read dispatch routine */
|
||||||
|
Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
|
||||||
|
|
||||||
|
if (Ret)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
/* the request was handeled */
|
||||||
|
return IoStatusBlock->Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (Flags == KSSTREAM_WRITE)
|
||||||
{
|
{
|
||||||
|
/* is fast write supported */
|
||||||
if (ObjectHeader->DispatchTable.FastWrite)
|
if (ObjectHeader->DispatchTable.FastWrite)
|
||||||
{
|
{
|
||||||
if (ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
|
/* call fast write dispatch routine */
|
||||||
|
Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
|
||||||
|
|
||||||
|
if (Ret)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
/* the request was handeled */
|
||||||
|
return IoStatusBlock->Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clear file object event */
|
||||||
|
KeClearEvent(&FileObject->Event);
|
||||||
|
|
||||||
|
/* set the offset to zero */
|
||||||
Offset.QuadPart = 0LL;
|
Offset.QuadPart = 0LL;
|
||||||
Irp = IoBuildSynchronousFsdRequest(Code, DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
|
|
||||||
|
/* now build the irp */
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
|
||||||
|
DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
|
||||||
if (!Irp)
|
if (!Irp)
|
||||||
{
|
{
|
||||||
return STATUS_UNSUCCESSFUL;
|
/* not enough memory */
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* setup irp parameters */
|
||||||
|
Irp->RequestorMode = RequestorMode;
|
||||||
|
Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
|
||||||
|
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||||
|
Irp->UserBuffer = StreamHeaders;
|
||||||
|
|
||||||
|
/* get next irp stack location */
|
||||||
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
/* setup stack parameters */
|
||||||
|
IoStack->FileObject = FileObject;
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength = Length;
|
||||||
|
IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders;
|
||||||
|
IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
|
||||||
|
|
||||||
if (CompletionRoutine)
|
if (CompletionRoutine)
|
||||||
{
|
{
|
||||||
IoSetCompletionRoutine(Irp,
|
/* setup completion routine for async processing */
|
||||||
CompletionRoutine,
|
IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
|
||||||
CompletionContext,
|
|
||||||
(CompletionInvocationFlags & KsInvokeOnSuccess),
|
|
||||||
(CompletionInvocationFlags & KsInvokeOnError),
|
|
||||||
(CompletionInvocationFlags & KsInvokeOnCancel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
/* now call the driver */
|
||||||
IoStack->FileObject = FileObject;
|
|
||||||
|
|
||||||
Status = IoCallDriver(DeviceObject, Irp);
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
/* done */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@unimplemented
|
@unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -933,7 +1003,7 @@ KsRemoveIrpFromCancelableQueue(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get irp offset */
|
/* get irp offset */
|
||||||
Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry);
|
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
if (Irp->Cancel)
|
if (Irp->Cancel)
|
||||||
{
|
{
|
||||||
|
@ -988,7 +1058,7 @@ KsRemoveIrpFromCancelableQueue(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@unimplemented
|
@implemented
|
||||||
*/
|
*/
|
||||||
KSDDKAPI
|
KSDDKAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1002,8 +1072,114 @@ KsMoveIrpsOnCancelableQueue(
|
||||||
IN PFNKSIRPLISTCALLBACK ListCallback,
|
IN PFNKSIRPLISTCALLBACK ListCallback,
|
||||||
IN PVOID Context)
|
IN PVOID Context)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
KIRQL OldLevel;
|
||||||
return STATUS_UNSUCCESSFUL;
|
PLIST_ENTRY SrcEntry;
|
||||||
|
PIRP Irp;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (!DestinationLock)
|
||||||
|
{
|
||||||
|
/* no destination lock just acquire the source lock */
|
||||||
|
KeAcquireSpinLock(SourceLock, &OldLevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* acquire cancel spinlock */
|
||||||
|
IoAcquireCancelSpinLock(&OldLevel);
|
||||||
|
|
||||||
|
/* now acquire source lock */
|
||||||
|
KeAcquireSpinLockAtDpcLevel(SourceLock);
|
||||||
|
|
||||||
|
/* now acquire destination lock */
|
||||||
|
KeAcquireSpinLockAtDpcLevel(DestinationLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* point to list head */
|
||||||
|
SrcEntry = SourceList;
|
||||||
|
|
||||||
|
/* now move all irps */
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
if (ListLocation == KsListEntryTail)
|
||||||
|
{
|
||||||
|
/* move queue downwards */
|
||||||
|
SrcEntry = SrcEntry->Flink;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* move queue upwards */
|
||||||
|
SrcEntry = SrcEntry->Blink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SrcEntry == DestinationList)
|
||||||
|
{
|
||||||
|
/* eof list reached */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get irp offset */
|
||||||
|
Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
/* now check if irp can be moved */
|
||||||
|
Status = ListCallback(Irp, Context);
|
||||||
|
|
||||||
|
/* check if irp can be moved */
|
||||||
|
if (Status == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* remove irp from src list */
|
||||||
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
if (ListLocation == KsListEntryTail)
|
||||||
|
{
|
||||||
|
/* insert irp end of list */
|
||||||
|
InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* insert irp head of list */
|
||||||
|
InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we need to update the irp lock */
|
||||||
|
if (DestinationLock)
|
||||||
|
{
|
||||||
|
/* update irp lock */
|
||||||
|
KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Status != STATUS_NO_MATCH)
|
||||||
|
{
|
||||||
|
/* callback decided to stop enumeration */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset return value */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DestinationLock)
|
||||||
|
{
|
||||||
|
/* release source lock */
|
||||||
|
KeReleaseSpinLock(SourceLock, OldLevel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* now release destination lock */
|
||||||
|
KeReleaseSpinLockFromDpcLevel(DestinationLock);
|
||||||
|
|
||||||
|
/* now release source lock */
|
||||||
|
KeReleaseSpinLockFromDpcLevel(SourceLock);
|
||||||
|
|
||||||
|
|
||||||
|
/* now release cancel spinlock */
|
||||||
|
IoReleaseCancelSpinLock(OldLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -197,7 +197,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
|
||||||
IN PKSDATAFORMAT DataFormat,
|
IN PKSDATAFORMAT DataFormat,
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN ULONG FrameSize,
|
IN ULONG FrameSize,
|
||||||
IN ULONG Alignment);
|
IN ULONG Alignment,
|
||||||
|
IN PVOID SilenceBuffer);
|
||||||
|
|
||||||
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
|
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
|
||||||
IN PUCHAR Buffer,
|
IN PUCHAR Buffer,
|
||||||
|
|
|
@ -8,17 +8,6 @@
|
||||||
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
typedef struct _IRP_MAPPING_
|
|
||||||
{
|
|
||||||
LIST_ENTRY Entry;
|
|
||||||
PVOID Buffer;
|
|
||||||
ULONG BufferSize;
|
|
||||||
ULONG OriginalBufferSize;
|
|
||||||
PVOID OriginalBuffer;
|
|
||||||
PIRP Irp;
|
|
||||||
|
|
||||||
PVOID Tag;
|
|
||||||
}IRP_MAPPING, *PIRP_MAPPING;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -33,9 +22,11 @@ typedef struct
|
||||||
KSPIN_CONNECT *ConnectDetails;
|
KSPIN_CONNECT *ConnectDetails;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
||||||
|
|
||||||
KSPIN_LOCK Lock;
|
KSPIN_LOCK IrpListLock;
|
||||||
LIST_ENTRY ListHead;
|
LIST_ENTRY IrpList;
|
||||||
LIST_ENTRY FreeHead;
|
LIST_ENTRY FreeIrpList;
|
||||||
|
PIRP Irp;
|
||||||
|
PVOID SilenceBuffer;
|
||||||
|
|
||||||
ULONG OutOfMapping;
|
ULONG OutOfMapping;
|
||||||
ULONG MaxFrameSize;
|
ULONG MaxFrameSize;
|
||||||
|
@ -44,28 +35,6 @@ typedef struct
|
||||||
|
|
||||||
}IIrpQueueImpl;
|
}IIrpQueueImpl;
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
FreeMappingRoutine(
|
|
||||||
PIRP_MAPPING CurMapping)
|
|
||||||
{
|
|
||||||
ASSERT(CurMapping);
|
|
||||||
|
|
||||||
if (CurMapping->Irp)
|
|
||||||
{
|
|
||||||
CurMapping->Irp->IoStatus.Information = CurMapping->OriginalBufferSize;
|
|
||||||
CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurMapping->OriginalBuffer)
|
|
||||||
{
|
|
||||||
ExFreePool(CurMapping->OriginalBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExFreePool(CurMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
IIrpQueue_fnQueryInterface(
|
IIrpQueue_fnQueryInterface(
|
||||||
|
@ -121,19 +90,21 @@ IIrpQueue_fnInit(
|
||||||
IN PKSDATAFORMAT DataFormat,
|
IN PKSDATAFORMAT DataFormat,
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN ULONG FrameSize,
|
IN ULONG FrameSize,
|
||||||
IN ULONG Alignment)
|
IN ULONG Alignment,
|
||||||
|
IN PVOID SilenceBuffer)
|
||||||
{
|
{
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
This->ConnectDetails = ConnectDetails;
|
This->ConnectDetails = ConnectDetails;
|
||||||
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
||||||
This->MaxFrameSize = FrameSize;
|
This->MaxFrameSize = FrameSize;
|
||||||
|
This->SilenceBuffer = SilenceBuffer;
|
||||||
This->Alignment = Alignment;
|
This->Alignment = Alignment;
|
||||||
This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
|
This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
|
||||||
|
|
||||||
InitializeListHead(&This->ListHead);
|
InitializeListHead(&This->IrpList);
|
||||||
InitializeListHead(&This->FreeHead);
|
InitializeListHead(&This->FreeIrpList);
|
||||||
KeInitializeSpinLock(&This->Lock);
|
KeInitializeSpinLock(&This->IrpListLock);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -146,84 +117,35 @@ IIrpQueue_fnAddMapping(
|
||||||
IN ULONG BufferSize,
|
IN ULONG BufferSize,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PIRP_MAPPING Mapping = NULL;
|
PKSSTREAM_HEADER Header;
|
||||||
KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
|
|
||||||
ULONG Index, NumMappings, Offset;
|
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
|
/* FIXME
|
||||||
|
* irp should contain the stream header...
|
||||||
|
*/
|
||||||
|
|
||||||
if (This->MaxFrameSize)
|
/* get stream header */
|
||||||
{
|
Header = (KSSTREAM_HEADER*)Buffer;
|
||||||
if (This->MaxFrameSize > Header->DataUsed)
|
|
||||||
{
|
|
||||||
/* small mapping */
|
|
||||||
NumMappings = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ULONG Rest = Header->DataUsed % This->MaxFrameSize;
|
|
||||||
|
|
||||||
NumMappings = Header->DataUsed / This->MaxFrameSize;
|
/* dont exceed max frame size */
|
||||||
if (Rest)
|
ASSERT(This->MaxFrameSize >= Header->DataUsed);
|
||||||
{
|
|
||||||
NumMappings++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no framesize restriction */
|
|
||||||
NumMappings = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Index = 0; Index < NumMappings; Index++)
|
/* hack untill stream probing is ready */
|
||||||
{
|
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
|
||||||
Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
|
|
||||||
if (!Mapping)
|
|
||||||
{
|
|
||||||
DPRINT("OutOfMemory\n");
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Index)
|
/* increment num mappings */
|
||||||
Offset = Index * This->MaxFrameSize;
|
InterlockedIncrement(&This->NumMappings);
|
||||||
else
|
|
||||||
Offset = 0;
|
|
||||||
|
|
||||||
Mapping->Buffer = (PVOID)UlongToPtr((PtrToUlong(Header->Data) + Offset + 3) & ~(0x3));
|
/* increment num data available */
|
||||||
|
This->NumDataAvailable += Header->DataUsed;
|
||||||
|
|
||||||
if (This->MaxFrameSize)
|
/* mark irp as pending */
|
||||||
Mapping->BufferSize = min(Header->DataUsed - Offset, This->MaxFrameSize);
|
|
||||||
else
|
|
||||||
Mapping->BufferSize = Header->DataUsed;
|
|
||||||
|
|
||||||
Mapping->OriginalBufferSize = Header->FrameExtent;
|
|
||||||
Mapping->OriginalBuffer = NULL;
|
|
||||||
Mapping->Irp = NULL;
|
|
||||||
Mapping->Tag = NULL;
|
|
||||||
|
|
||||||
This->NumDataAvailable += Mapping->BufferSize;
|
|
||||||
|
|
||||||
if (Index == NumMappings - 1)
|
|
||||||
{
|
|
||||||
/* last mapping should free the irp if provided */
|
|
||||||
Mapping->OriginalBuffer = Header->Data;
|
|
||||||
Mapping->Irp = Irp;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExInterlockedInsertTailList(&This->ListHead, &Mapping->Entry, &This->Lock);
|
|
||||||
(void)InterlockedIncrement((volatile long*)&This->NumMappings);
|
|
||||||
|
|
||||||
DPRINT("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu NumDataAvailable %lu Mapping %p FrameSize %u\n", This->NumMappings, Mapping->BufferSize, This->NumDataAvailable, Mapping, This->MaxFrameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Irp)
|
|
||||||
{
|
|
||||||
Irp->IoStatus.Status = STATUS_PENDING;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
}
|
|
||||||
|
|
||||||
|
/* add irp to cancelable queue */
|
||||||
|
KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL);
|
||||||
|
|
||||||
|
/* done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,55 +156,102 @@ IIrpQueue_fnGetMapping(
|
||||||
OUT PUCHAR * Buffer,
|
OUT PUCHAR * Buffer,
|
||||||
OUT PULONG BufferSize)
|
OUT PULONG BufferSize)
|
||||||
{
|
{
|
||||||
|
PIRP Irp;
|
||||||
PIRP_MAPPING CurMapping;
|
ULONG Offset;
|
||||||
|
PKSSTREAM_HEADER StreamHeader;
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
PLIST_ENTRY CurEntry;
|
|
||||||
|
|
||||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
/* check if there is an irp in the partially processed */
|
||||||
if (!CurEntry)
|
if (This->Irp)
|
||||||
{
|
{
|
||||||
This->StartStream = FALSE;
|
/* use last irp */
|
||||||
This->OutOfMapping = TRUE;
|
Irp = This->Irp;
|
||||||
return STATUS_UNSUCCESSFUL;
|
Offset = This->CurrentOffset;
|
||||||
|
/* TODO cancel irp when required */
|
||||||
|
ASSERT(Irp->Cancel == FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* get a fresh new irp from the queue */
|
||||||
|
This->Irp = Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
|
||||||
|
This->CurrentOffset = Offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
if (!Irp)
|
||||||
*Buffer = (PUCHAR)CurMapping->Buffer + This->CurrentOffset;
|
{
|
||||||
*BufferSize = CurMapping->BufferSize - This->CurrentOffset;
|
/* no irp available, use silence buffer */
|
||||||
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
|
*Buffer = This->SilenceBuffer;
|
||||||
|
*BufferSize = This->MaxFrameSize;
|
||||||
|
/* flag for port wave pci driver */
|
||||||
|
This->OutOfMapping = TRUE;
|
||||||
|
/* indicate flag to restart fast buffering */
|
||||||
|
This->StartStream = FALSE;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HACK get stream header */
|
||||||
|
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(StreamHeader);
|
||||||
|
|
||||||
|
/* store buffersize */
|
||||||
|
*BufferSize = StreamHeader->DataUsed - Offset;
|
||||||
|
|
||||||
|
/* store buffer */
|
||||||
|
*Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
|
||||||
|
|
||||||
|
/* unset flag that no irps are available */
|
||||||
This->OutOfMapping = FALSE;
|
This->OutOfMapping = FALSE;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
IIrpQueue_fnUpdateMapping(
|
IIrpQueue_fnUpdateMapping(
|
||||||
IN IIrpQueue *iface,
|
IN IIrpQueue *iface,
|
||||||
IN ULONG BytesWritten)
|
IN ULONG BytesWritten)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY CurEntry;
|
PKSSTREAM_HEADER StreamHeader;
|
||||||
PIRP_MAPPING CurMapping;
|
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
if (!This->Irp)
|
||||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
{
|
||||||
|
/* silence buffer was used */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HACK get stream header */
|
||||||
|
StreamHeader = (PKSSTREAM_HEADER)This->Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
|
||||||
|
/* add to current offset */
|
||||||
This->CurrentOffset += BytesWritten;
|
This->CurrentOffset += BytesWritten;
|
||||||
|
|
||||||
|
/* decrement available data counter */
|
||||||
This->NumDataAvailable -= BytesWritten;
|
This->NumDataAvailable -= BytesWritten;
|
||||||
|
|
||||||
if (CurMapping->BufferSize <= This->CurrentOffset)
|
if (This->CurrentOffset >= StreamHeader->DataUsed)
|
||||||
{
|
{
|
||||||
|
/* irp has been processed completly */
|
||||||
|
This->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
|
||||||
|
*/
|
||||||
|
This->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);
|
||||||
|
|
||||||
|
/* complete the request */
|
||||||
|
IoCompleteRequest(This->Irp, IO_SOUND_INCREMENT);
|
||||||
|
/* remove irp as it is complete */
|
||||||
|
This->Irp = NULL;
|
||||||
This->CurrentOffset = 0;
|
This->CurrentOffset = 0;
|
||||||
InterlockedDecrement(&This->NumMappings);
|
|
||||||
FreeMappingRoutine(CurMapping);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,6 +262,7 @@ IIrpQueue_fnNumMappings(
|
||||||
{
|
{
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
|
/* returns the amount of mappings available */
|
||||||
return This->NumMappings;
|
return This->NumMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,6 +272,7 @@ IIrpQueue_fnNumData(
|
||||||
IN IIrpQueue *iface)
|
IN IIrpQueue *iface)
|
||||||
{
|
{
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
/* returns the amount of audio stream data available */
|
||||||
return This->NumDataAvailable;
|
return This->NumDataAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,50 +334,45 @@ IIrpQueue_fnGetMappingWithTag(
|
||||||
OUT PULONG ByteCount,
|
OUT PULONG ByteCount,
|
||||||
OUT PULONG Flags)
|
OUT PULONG Flags)
|
||||||
{
|
{
|
||||||
PIRP_MAPPING CurMapping;
|
PKSSTREAM_HEADER StreamHeader;
|
||||||
PLIST_ENTRY CurEntry;
|
PIRP Irp;
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
*Flags = 0;
|
*Flags = 0;
|
||||||
ASSERT(Tag != NULL);
|
ASSERT(Tag != NULL);
|
||||||
|
|
||||||
|
/* get an irp from the queue */
|
||||||
|
Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
|
||||||
|
|
||||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
/* check if there is an irp */
|
||||||
if (!CurEntry)
|
if (!Irp)
|
||||||
{
|
{
|
||||||
|
/* no irp available */
|
||||||
This->OutOfMapping = TRUE;
|
This->OutOfMapping = TRUE;
|
||||||
This->StartStream = FALSE;
|
This->StartStream = FALSE;
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
/* HACK get stream header */
|
||||||
|
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
|
||||||
*PhysicalAddress = MmGetPhysicalAddress(CurMapping->Buffer);
|
/* store mapping in the free list */
|
||||||
*VirtualAddress = CurMapping->Buffer;
|
ExInterlockedInsertTailList(&This->FreeIrpList, &Irp->Tail.Overlay.ListEntry, &This->IrpListLock);
|
||||||
*ByteCount = CurMapping->BufferSize;
|
|
||||||
|
|
||||||
|
/* return mapping */
|
||||||
|
*PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
|
||||||
|
*VirtualAddress = StreamHeader->Data;
|
||||||
|
*ByteCount = StreamHeader->DataUsed;
|
||||||
|
|
||||||
|
/* decrement mapping count */
|
||||||
InterlockedDecrement(&This->NumMappings);
|
InterlockedDecrement(&This->NumMappings);
|
||||||
This->NumDataAvailable -= CurMapping->BufferSize;
|
/* decrement num data available */
|
||||||
|
This->NumDataAvailable -= StreamHeader->DataUsed;
|
||||||
|
|
||||||
if (CurMapping->OriginalBuffer)
|
/* store tag in irp */
|
||||||
{
|
Irp->Tail.Overlay.DriverContext[3] = Tag;
|
||||||
/* last partial buffer */
|
|
||||||
*Flags = 1;
|
|
||||||
|
|
||||||
/* store tag */
|
|
||||||
CurMapping->Tag = Tag;
|
|
||||||
|
|
||||||
/* insert into list to free later */
|
|
||||||
ExInterlockedInsertTailList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
|
|
||||||
DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p\n", Tag, CurMapping);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* we can free this entry now */
|
|
||||||
FreeItem(CurMapping, TAG_PORTCLASS);
|
|
||||||
DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,30 +382,44 @@ IIrpQueue_fnReleaseMappingWithTag(
|
||||||
IN IIrpQueue *iface,
|
IN IIrpQueue *iface,
|
||||||
IN PVOID Tag)
|
IN PVOID Tag)
|
||||||
{
|
{
|
||||||
PIRP_MAPPING CurMapping = NULL;
|
PIRP Irp;
|
||||||
PLIST_ENTRY CurEntry;
|
PLIST_ENTRY CurEntry;
|
||||||
|
PKSSTREAM_HEADER StreamHeader;
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||||
|
|
||||||
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
|
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
|
||||||
|
|
||||||
CurEntry = ExInterlockedRemoveHeadList(&This->FreeHead, &This->Lock);
|
/* remove irp from used list */
|
||||||
if (!CurMapping)
|
CurEntry = ExInterlockedRemoveHeadList(&This->FreeIrpList, &This->IrpListLock);
|
||||||
{
|
/* sanity check */
|
||||||
return STATUS_SUCCESS;
|
ASSERT(CurEntry);
|
||||||
}
|
|
||||||
|
|
||||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
/* get irp from list entry */
|
||||||
if (CurMapping->Tag != Tag)
|
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
{
|
|
||||||
/* the released mapping is not the last one */
|
|
||||||
ExInterlockedInsertHeadList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* last mapping of the irp, free irp */
|
/* HACK get stream header */
|
||||||
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
|
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
|
||||||
|
/* driver must release items in the same order */
|
||||||
|
ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag);
|
||||||
|
|
||||||
|
/* irp has been processed completly */
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* complete the request */
|
||||||
|
IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
|
||||||
|
|
||||||
FreeMappingRoutine(CurMapping);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,24 +437,7 @@ NTAPI
|
||||||
IIrpQueue_fnPrintQueueStatus(
|
IIrpQueue_fnPrintQueueStatus(
|
||||||
IN IIrpQueue *iface)
|
IN IIrpQueue *iface)
|
||||||
{
|
{
|
||||||
PIRP_MAPPING CurMapping = NULL;
|
|
||||||
PLIST_ENTRY CurEntry;
|
|
||||||
|
|
||||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&This->Lock);
|
|
||||||
|
|
||||||
CurEntry = This->ListHead.Flink;
|
|
||||||
DPRINT("IIrpQueue_fnPrintQueueStatus % u ===============\n", This->NumMappings);
|
|
||||||
|
|
||||||
while (CurEntry != &This->ListHead)
|
|
||||||
{
|
|
||||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
|
||||||
DPRINT("Mapping %p Size %u Original %p\n", CurMapping, CurMapping->BufferSize, CurMapping->OriginalBuffer);
|
|
||||||
CurEntry = CurEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeReleaseSpinLockFromDpcLevel(&This->Lock);
|
|
||||||
DPRINT("IIrpQueue_fnPrintQueueStatus ===============\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ IPortPinDMus_fnInit(
|
||||||
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
|
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, 0, 0);
|
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, 0, 0, NULL /*FIXME*/);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||||
|
|
|
@ -970,38 +970,25 @@ IPortPinWaveCyclic_fnFastWrite(
|
||||||
PrePostRatio = (This->PreCompleted * 100) / This->TotalPackets;
|
PrePostRatio = (This->PreCompleted * 100) / This->TotalPackets;
|
||||||
MinData = This->IrpQueue->lpVtbl->NumData(This->IrpQueue);
|
MinData = This->IrpQueue->lpVtbl->NumData(This->IrpQueue);
|
||||||
|
|
||||||
DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x MinData %u Ratio %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue), PrePostRatio);
|
DPRINT1("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x MinData %u Ratio %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted, This->State, This->IrpQueue->lpVtbl->NumData(This->IrpQueue), PrePostRatio);
|
||||||
|
|
||||||
Packet = (PCONTEXT_WRITE)Buffer;
|
Packet = (PCONTEXT_WRITE)Buffer;
|
||||||
|
|
||||||
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
|
||||||
{
|
|
||||||
Irp = Packet->Irp;
|
Irp = Packet->Irp;
|
||||||
StatusBlock->Status = STATUS_PENDING;
|
|
||||||
InterlockedIncrement((PLONG)&This->PostCompleted);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Irp = NULL;
|
|
||||||
Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent;
|
|
||||||
IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
|
|
||||||
StatusBlock->Status = STATUS_SUCCESS;
|
|
||||||
InterlockedIncrement((PLONG)&This->PreCompleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (This->State != KSSTATE_RUN && This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE)
|
if (This->State != KSSTATE_RUN)
|
||||||
{
|
{
|
||||||
SetStreamState(This, KSSTATE_RUN);
|
SetStreamState(This, KSSTATE_RUN);
|
||||||
/* some should initiate a state request but didnt do it */
|
/* some should initiate a state request but didnt do it */
|
||||||
DPRINT1("Starting stream with %lu mappings Status %x\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), Status);
|
DPRINT1("Starting stream with %lu mappings Status %x\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBlock->Status = STATUS_PENDING;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,6 +1008,7 @@ IPortPinWaveCyclic_fnInit(
|
||||||
PKSDATAFORMAT DataFormat;
|
PKSDATAFORMAT DataFormat;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
BOOL Capture;
|
BOOL Capture;
|
||||||
|
PVOID SilenceBuffer;
|
||||||
//IDrmAudioStream * DrmAudio = NULL;
|
//IDrmAudioStream * DrmAudio = NULL;
|
||||||
|
|
||||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||||
|
@ -1114,14 +1102,19 @@ IPortPinWaveCyclic_fnInit(
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, This->FrameSize, 0);
|
SilenceBuffer = AllocateItem(NonPagedPool, This->FrameSize, TAG_PORTCLASS);
|
||||||
|
if (!SilenceBuffer)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
This->Stream->lpVtbl->Silence(This->Stream, SilenceBuffer, This->FrameSize);
|
||||||
|
|
||||||
|
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, This->FrameSize, 0, SilenceBuffer);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
This->IrpQueue->lpVtbl->Release(This->IrpQueue);
|
This->IrpQueue->lpVtbl->Release(This->IrpQueue);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
|
//This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
|
||||||
DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE));
|
DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE));
|
||||||
DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
|
DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
|
||||||
|
|
|
@ -1069,7 +1069,7 @@ IPortPinWavePci_fnInit(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, This->AllocatorFraming.FrameSize, This->AllocatorFraming.FileAlignment);
|
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, This->AllocatorFraming.FrameSize, This->AllocatorFraming.FileAlignment, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||||
|
|
|
@ -992,7 +992,7 @@ IPortPinWaveRT_fnInit(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, 0, 0);
|
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, 0, 0, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
|
@ -668,6 +668,8 @@ Pin_fnFastWrite(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IoStatus->Status = Status;
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else
|
else
|
||||||
|
|
|
@ -704,6 +704,28 @@ WdmAudDeviceControl(
|
||||||
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
WdmAudWrite(
|
WdmAudWrite(
|
||||||
|
@ -715,11 +737,13 @@ WdmAudWrite(
|
||||||
PWDMAUD_CLIENT ClientInfo;
|
PWDMAUD_CLIENT ClientInfo;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer;
|
||||||
PCONTEXT_WRITE Packet;
|
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
//PIRP LowerIrp;
|
||||||
|
PCONTEXT_WRITE Packet;
|
||||||
PVOID SystemBuffer;
|
PVOID SystemBuffer;
|
||||||
|
//LARGE_INTEGER Offset;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
@ -826,14 +850,51 @@ WdmAudWrite(
|
||||||
ExFreePool(Packet);
|
ExFreePool(Packet);
|
||||||
IoFreeMdl(Mdl);
|
IoFreeMdl(Mdl);
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->BufferSize);
|
RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->BufferSize);
|
||||||
MmUnlockPages(Mdl);
|
MmUnlockPages(Mdl);
|
||||||
IoFreeMdl(Mdl);
|
IoFreeMdl(Mdl);
|
||||||
|
|
||||||
KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, KernelMode);
|
#if 1
|
||||||
|
KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, UserMode);
|
||||||
|
/* dereference file object */
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return IoStatusBlock.Status;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a completion routine */
|
||||||
|
IoSetCompletionRoutine(LowerIrp, WdmAudWriteCompletion, (PVOID)Irp, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
/* mark irp as pending */
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
|
||||||
|
/* call the driver */
|
||||||
|
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), LowerIrp);
|
||||||
|
|
||||||
|
/* dereference file object */
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
|
return STATUS_PENDING;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,15 +56,6 @@ typedef struct
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
}CONTEXT_WRITE, *PCONTEXT_WRITE;
|
}CONTEXT_WRITE, *PCONTEXT_WRITE;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
PIRP Irp;
|
|
||||||
IO_STATUS_BLOCK StatusBlock;
|
|
||||||
ULONG Length;
|
|
||||||
}WRITE_CONTEXT, *PWRITE_CONTEXT;
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
WdmAudRegisterDeviceInterface(
|
WdmAudRegisterDeviceInterface(
|
||||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||||
|
|
|
@ -161,7 +161,7 @@ Pin_fnWrite(
|
||||||
|
|
||||||
/* call the portcls audio pin */
|
/* call the portcls audio pin */
|
||||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
||||||
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
Irp->UserBuffer,
|
||||||
IoStack->Parameters.Write.Length,
|
IoStack->Parameters.Write.Length,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
|
@ -379,13 +379,14 @@ Pin_fnFastWrite(
|
||||||
Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
|
Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
|
Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
|
||||||
ObDereferenceObject(RealFileObject);
|
ObDereferenceObject(RealFileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Mixing stream failed with %lx\n", Status);
|
DPRINT1("Mixing stream failed with %lx\n", Status);
|
||||||
|
DbgBreakPoint();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,11 +395,11 @@ Pin_fnFastWrite(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
|
Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
|
||||||
|
|
||||||
ObDereferenceObject(RealFileObject);
|
ObDereferenceObject(RealFileObject);
|
||||||
|
|
||||||
if (Status == STATUS_SUCCESS)
|
if (NT_SUCCESS(Status))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue