mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +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
|
||||
NTSTATUS
|
||||
|
@ -357,7 +357,13 @@ KsQueryInformationFile(
|
|||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PFAST_IO_DISPATCH FastIoDispatch;
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
KEVENT Event;
|
||||
LARGE_INTEGER Offset;
|
||||
IO_STATUS_BLOCK StatusBlock;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get related file object */
|
||||
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;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
ULONG Code;
|
||||
NTSTATUS Status;
|
||||
LARGE_INTEGER Offset;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
BOOLEAN Ret;
|
||||
|
||||
|
||||
if (Flags == KSSTREAM_READ)
|
||||
Code = IRP_MJ_READ;
|
||||
else if (Flags == KSSTREAM_WRITE)
|
||||
Code = IRP_MJ_WRITE;
|
||||
else
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* get related device object */
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
if (!DeviceObject)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
/* sanity check */
|
||||
ASSERT(DeviceObject != NULL);
|
||||
|
||||
/* is there a event provided */
|
||||
if (Event)
|
||||
{
|
||||
KeResetEvent(Event);
|
||||
/* reset event */
|
||||
KeClearEvent(Event);
|
||||
}
|
||||
|
||||
//ASSERT(DeviceObject->DeviceType == FILE_DEVICE_KS);
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
ASSERT(ObjectHeader);
|
||||
if (Code == IRP_MJ_READ)
|
||||
if (RequestorMode || ExGetPreviousMode() == KernelMode)
|
||||
{
|
||||
if (ObjectHeader->DispatchTable.FastRead)
|
||||
/* requestor is from kernel land */
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
|
||||
if (ObjectHeader)
|
||||
{
|
||||
if (ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
|
||||
/* there is a object header */
|
||||
if (Flags == KSSTREAM_READ)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
/* is fast read supported */
|
||||
if (ObjectHeader->DispatchTable.FastRead)
|
||||
{
|
||||
/* call fast read dispatch routine */
|
||||
Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
/* the request was handeled */
|
||||
return IoStatusBlock->Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ObjectHeader->DispatchTable.FastWrite)
|
||||
{
|
||||
if (ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
|
||||
else if (Flags == KSSTREAM_WRITE)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
/* is fast write supported */
|
||||
if (ObjectHeader->DispatchTable.FastWrite)
|
||||
{
|
||||
/* call fast write dispatch routine */
|
||||
Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
|
||||
|
||||
if (Ret)
|
||||
{
|
||||
/* the request was handeled */
|
||||
return IoStatusBlock->Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clear file object event */
|
||||
KeClearEvent(&FileObject->Event);
|
||||
|
||||
/* set the offset to zero */
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
IoSetCompletionRoutine(Irp,
|
||||
CompletionRoutine,
|
||||
CompletionContext,
|
||||
(CompletionInvocationFlags & KsInvokeOnSuccess),
|
||||
(CompletionInvocationFlags & KsInvokeOnError),
|
||||
(CompletionInvocationFlags & KsInvokeOnCancel));
|
||||
/* setup completion routine for async processing */
|
||||
IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
|
||||
}
|
||||
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->FileObject = FileObject;
|
||||
|
||||
/* now call the driver */
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
|
@ -933,7 +1003,7 @@ KsRemoveIrpFromCancelableQueue(
|
|||
}
|
||||
|
||||
/* get irp offset */
|
||||
Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry);
|
||||
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
if (Irp->Cancel)
|
||||
{
|
||||
|
@ -988,7 +1058,7 @@ KsRemoveIrpFromCancelableQueue(
|
|||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
|
@ -1002,8 +1072,114 @@ KsMoveIrpsOnCancelableQueue(
|
|||
IN PFNKSIRPLISTCALLBACK ListCallback,
|
||||
IN PVOID Context)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
KIRQL OldLevel;
|
||||
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 PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG FrameSize,
|
||||
IN ULONG Alignment);
|
||||
IN ULONG Alignment,
|
||||
IN PVOID SilenceBuffer);
|
||||
|
||||
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
|
||||
IN PUCHAR Buffer,
|
||||
|
|
|
@ -8,17 +8,6 @@
|
|||
|
||||
#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
|
||||
{
|
||||
|
@ -33,9 +22,11 @@ typedef struct
|
|||
KSPIN_CONNECT *ConnectDetails;
|
||||
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
||||
|
||||
KSPIN_LOCK Lock;
|
||||
LIST_ENTRY ListHead;
|
||||
LIST_ENTRY FreeHead;
|
||||
KSPIN_LOCK IrpListLock;
|
||||
LIST_ENTRY IrpList;
|
||||
LIST_ENTRY FreeIrpList;
|
||||
PIRP Irp;
|
||||
PVOID SilenceBuffer;
|
||||
|
||||
ULONG OutOfMapping;
|
||||
ULONG MaxFrameSize;
|
||||
|
@ -44,28 +35,6 @@ typedef struct
|
|||
|
||||
}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
|
||||
NTAPI
|
||||
IIrpQueue_fnQueryInterface(
|
||||
|
@ -121,19 +90,21 @@ IIrpQueue_fnInit(
|
|||
IN PKSDATAFORMAT DataFormat,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG FrameSize,
|
||||
IN ULONG Alignment)
|
||||
IN ULONG Alignment,
|
||||
IN PVOID SilenceBuffer)
|
||||
{
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
This->ConnectDetails = ConnectDetails;
|
||||
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
||||
This->MaxFrameSize = FrameSize;
|
||||
This->SilenceBuffer = SilenceBuffer;
|
||||
This->Alignment = Alignment;
|
||||
This->MinimumDataThreshold = ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
|
||||
|
||||
InitializeListHead(&This->ListHead);
|
||||
InitializeListHead(&This->FreeHead);
|
||||
KeInitializeSpinLock(&This->Lock);
|
||||
InitializeListHead(&This->IrpList);
|
||||
InitializeListHead(&This->FreeIrpList);
|
||||
KeInitializeSpinLock(&This->IrpListLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -146,84 +117,35 @@ IIrpQueue_fnAddMapping(
|
|||
IN ULONG BufferSize,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIRP_MAPPING Mapping = NULL;
|
||||
KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
|
||||
ULONG Index, NumMappings, Offset;
|
||||
PKSSTREAM_HEADER Header;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
/* FIXME
|
||||
* irp should contain the stream header...
|
||||
*/
|
||||
|
||||
if (This->MaxFrameSize)
|
||||
{
|
||||
if (This->MaxFrameSize > Header->DataUsed)
|
||||
{
|
||||
/* small mapping */
|
||||
NumMappings = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG Rest = Header->DataUsed % This->MaxFrameSize;
|
||||
/* get stream header */
|
||||
Header = (KSSTREAM_HEADER*)Buffer;
|
||||
|
||||
NumMappings = Header->DataUsed / This->MaxFrameSize;
|
||||
if (Rest)
|
||||
{
|
||||
NumMappings++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no framesize restriction */
|
||||
NumMappings = 1;
|
||||
}
|
||||
/* dont exceed max frame size */
|
||||
ASSERT(This->MaxFrameSize >= Header->DataUsed);
|
||||
|
||||
for(Index = 0; Index < NumMappings; Index++)
|
||||
{
|
||||
Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
|
||||
if (!Mapping)
|
||||
{
|
||||
DPRINT("OutOfMemory\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
/* hack untill stream probing is ready */
|
||||
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
|
||||
|
||||
if (Index)
|
||||
Offset = Index * This->MaxFrameSize;
|
||||
else
|
||||
Offset = 0;
|
||||
/* increment num mappings */
|
||||
InterlockedIncrement(&This->NumMappings);
|
||||
|
||||
Mapping->Buffer = (PVOID)UlongToPtr((PtrToUlong(Header->Data) + Offset + 3) & ~(0x3));
|
||||
/* increment num data available */
|
||||
This->NumDataAvailable += Header->DataUsed;
|
||||
|
||||
if (This->MaxFrameSize)
|
||||
Mapping->BufferSize = min(Header->DataUsed - Offset, This->MaxFrameSize);
|
||||
else
|
||||
Mapping->BufferSize = Header->DataUsed;
|
||||
/* mark irp as pending */
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
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);
|
||||
}
|
||||
/* add irp to cancelable queue */
|
||||
KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL);
|
||||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -234,55 +156,102 @@ IIrpQueue_fnGetMapping(
|
|||
OUT PUCHAR * Buffer,
|
||||
OUT PULONG BufferSize)
|
||||
{
|
||||
|
||||
PIRP_MAPPING CurMapping;
|
||||
PIRP Irp;
|
||||
ULONG Offset;
|
||||
PKSSTREAM_HEADER StreamHeader;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
PLIST_ENTRY CurEntry;
|
||||
|
||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
||||
if (!CurEntry)
|
||||
/* check if there is an irp in the partially processed */
|
||||
if (This->Irp)
|
||||
{
|
||||
This->StartStream = FALSE;
|
||||
This->OutOfMapping = TRUE;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
/* use last irp */
|
||||
Irp = This->Irp;
|
||||
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);
|
||||
*Buffer = (PUCHAR)CurMapping->Buffer + This->CurrentOffset;
|
||||
*BufferSize = CurMapping->BufferSize - This->CurrentOffset;
|
||||
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
|
||||
if (!Irp)
|
||||
{
|
||||
/* no irp available, use silence buffer */
|
||||
*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;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IIrpQueue_fnUpdateMapping(
|
||||
IN IIrpQueue *iface,
|
||||
IN ULONG BytesWritten)
|
||||
{
|
||||
PLIST_ENTRY CurEntry;
|
||||
PIRP_MAPPING CurMapping;
|
||||
PKSSTREAM_HEADER StreamHeader;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
||||
if (!This->Irp)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* decrement available data counter */
|
||||
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;
|
||||
InterlockedDecrement(&This->NumMappings);
|
||||
FreeMappingRoutine(CurMapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,6 +262,7 @@ IIrpQueue_fnNumMappings(
|
|||
{
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
/* returns the amount of mappings available */
|
||||
return This->NumMappings;
|
||||
}
|
||||
|
||||
|
@ -302,6 +272,7 @@ IIrpQueue_fnNumData(
|
|||
IN IIrpQueue *iface)
|
||||
{
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
/* returns the amount of audio stream data available */
|
||||
return This->NumDataAvailable;
|
||||
}
|
||||
|
||||
|
@ -363,50 +334,45 @@ IIrpQueue_fnGetMappingWithTag(
|
|||
OUT PULONG ByteCount,
|
||||
OUT PULONG Flags)
|
||||
{
|
||||
PIRP_MAPPING CurMapping;
|
||||
PLIST_ENTRY CurEntry;
|
||||
PKSSTREAM_HEADER StreamHeader;
|
||||
PIRP Irp;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
*Flags = 0;
|
||||
ASSERT(Tag != NULL);
|
||||
|
||||
/* get an irp from the queue */
|
||||
Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
|
||||
|
||||
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
|
||||
if (!CurEntry)
|
||||
/* check if there is an irp */
|
||||
if (!Irp)
|
||||
{
|
||||
/* no irp available */
|
||||
This->OutOfMapping = TRUE;
|
||||
This->StartStream = FALSE;
|
||||
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);
|
||||
*VirtualAddress = CurMapping->Buffer;
|
||||
*ByteCount = CurMapping->BufferSize;
|
||||
/* store mapping in the free list */
|
||||
ExInterlockedInsertTailList(&This->FreeIrpList, &Irp->Tail.Overlay.ListEntry, &This->IrpListLock);
|
||||
|
||||
/* return mapping */
|
||||
*PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
|
||||
*VirtualAddress = StreamHeader->Data;
|
||||
*ByteCount = StreamHeader->DataUsed;
|
||||
|
||||
/* decrement mapping count */
|
||||
InterlockedDecrement(&This->NumMappings);
|
||||
This->NumDataAvailable -= CurMapping->BufferSize;
|
||||
/* decrement num data available */
|
||||
This->NumDataAvailable -= StreamHeader->DataUsed;
|
||||
|
||||
if (CurMapping->OriginalBuffer)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
/* store tag in irp */
|
||||
Irp->Tail.Overlay.DriverContext[3] = Tag;
|
||||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -416,30 +382,44 @@ IIrpQueue_fnReleaseMappingWithTag(
|
|||
IN IIrpQueue *iface,
|
||||
IN PVOID Tag)
|
||||
{
|
||||
PIRP_MAPPING CurMapping = NULL;
|
||||
PIRP Irp;
|
||||
PLIST_ENTRY CurEntry;
|
||||
PKSSTREAM_HEADER StreamHeader;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
|
||||
|
||||
CurEntry = ExInterlockedRemoveHeadList(&This->FreeHead, &This->Lock);
|
||||
if (!CurMapping)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/* remove irp from used list */
|
||||
CurEntry = ExInterlockedRemoveHeadList(&This->FreeIrpList, &This->IrpListLock);
|
||||
/* sanity check */
|
||||
ASSERT(CurEntry);
|
||||
|
||||
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
|
||||
if (CurMapping->Tag != Tag)
|
||||
{
|
||||
/* the released mapping is not the last one */
|
||||
ExInterlockedInsertHeadList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/* get irp from list entry */
|
||||
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
/* last mapping of the irp, free irp */
|
||||
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
|
||||
/* HACK get stream header */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -457,24 +437,7 @@ NTAPI
|
|||
IIrpQueue_fnPrintQueueStatus(
|
||||
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
|
||||
|
|
|
@ -1135,7 +1135,7 @@ IPortPinDMus_fnInit(
|
|||
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))
|
||||
{
|
||||
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||
|
|
|
@ -970,38 +970,25 @@ IPortPinWaveCyclic_fnFastWrite(
|
|||
PrePostRatio = (This->PreCompleted * 100) / This->TotalPackets;
|
||||
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;
|
||||
|
||||
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
||||
{
|
||||
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);
|
||||
}
|
||||
Irp = Packet->Irp;
|
||||
|
||||
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return FALSE;
|
||||
|
||||
if (This->State != KSSTATE_RUN && This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE)
|
||||
if (This->State != KSSTATE_RUN)
|
||||
{
|
||||
SetStreamState(This, KSSTATE_RUN);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
StatusBlock->Status = STATUS_PENDING;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1021,6 +1008,7 @@ IPortPinWaveCyclic_fnInit(
|
|||
PKSDATAFORMAT DataFormat;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
BOOL Capture;
|
||||
PVOID SilenceBuffer;
|
||||
//IDrmAudioStream * DrmAudio = NULL;
|
||||
|
||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||
|
@ -1114,14 +1102,19 @@ IPortPinWaveCyclic_fnInit(
|
|||
|
||||
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))
|
||||
{
|
||||
This->IrpQueue->lpVtbl->Release(This->IrpQueue);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
//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 pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
|
||||
|
|
|
@ -1069,7 +1069,7 @@ IPortPinWavePci_fnInit(
|
|||
if (!NT_SUCCESS(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))
|
||||
{
|
||||
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||
|
|
|
@ -992,7 +992,7 @@ IPortPinWaveRT_fnInit(
|
|||
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))
|
||||
{
|
||||
goto cleanup;
|
||||
|
|
|
@ -668,6 +668,8 @@ Pin_fnFastWrite(
|
|||
}
|
||||
}
|
||||
|
||||
IoStatus->Status = Status;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
return TRUE;
|
||||
else
|
||||
|
|
|
@ -704,6 +704,28 @@ WdmAudDeviceControl(
|
|||
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(
|
||||
|
@ -715,11 +737,13 @@ WdmAudWrite(
|
|||
PWDMAUD_CLIENT ClientInfo;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PUCHAR Buffer;
|
||||
PCONTEXT_WRITE Packet;
|
||||
PFILE_OBJECT FileObject;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PMDL Mdl;
|
||||
//PIRP LowerIrp;
|
||||
PCONTEXT_WRITE Packet;
|
||||
PVOID SystemBuffer;
|
||||
//LARGE_INTEGER Offset;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
|
@ -826,14 +850,51 @@ WdmAudWrite(
|
|||
ExFreePool(Packet);
|
||||
IoFreeMdl(Mdl);
|
||||
ObDereferenceObject(FileObject);
|
||||
return SetIrpIoStatus(Irp, Status, 0);
|
||||
return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
|
||||
}
|
||||
|
||||
RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->BufferSize);
|
||||
MmUnlockPages(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);
|
||||
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;
|
||||
}CONTEXT_WRITE, *PCONTEXT_WRITE;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK StatusBlock;
|
||||
ULONG Length;
|
||||
}WRITE_CONTEXT, *PWRITE_CONTEXT;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
WdmAudRegisterDeviceInterface(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
|
|
|
@ -161,7 +161,7 @@ Pin_fnWrite(
|
|||
|
||||
/* call the portcls audio pin */
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
||||
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
||||
Irp->UserBuffer,
|
||||
IoStack->Parameters.Write.Length,
|
||||
NULL,
|
||||
0,
|
||||
|
@ -379,13 +379,14 @@ Pin_fnFastWrite(
|
|||
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, KernelMode);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -394,11 +395,11 @@ Pin_fnFastWrite(
|
|||
if (!NT_SUCCESS(Status))
|
||||
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);
|
||||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
if (NT_SUCCESS(Status))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
|
Loading…
Reference in a new issue