mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-01 04:13:35 +00:00
- Wait for the APC in wdmaud.drv
- Queue ~ one second of audio data before starting to stream - Check if an audio pin is already open and re-use it in that case svn path=/trunk/; revision=39907
This commit is contained in:
@@ -309,10 +309,8 @@ WriteFileEx_Committer2(
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HACK
|
||||
* The CompletionRoutine should be called by the system
|
||||
*/
|
||||
CompletionRoutine(0, Length, (LPOVERLAPPED)Overlap);
|
||||
WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
|
||||
|
||||
}
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
@@ -193,6 +193,7 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
|
||||
|
||||
STDMETHOD_(NTSTATUS, Init)(THIS_
|
||||
IN KSPIN_CONNECT *ConnectDetails,
|
||||
IN PKSDATAFORMAT DataFormat,
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
|
||||
@@ -211,7 +212,7 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
|
||||
|
||||
STDMETHOD_(ULONG, MinMappings)(THIS);
|
||||
|
||||
STDMETHOD_(ULONG, MaxMappings)(THIS);
|
||||
STDMETHOD_(BOOL, MinimumDataAvailable)(THIS);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ typedef struct _IRP_MAPPING_
|
||||
struct _IRP_MAPPING_ * Next;
|
||||
}IRP_MAPPING, *PIRP_MAPPING;
|
||||
|
||||
#define MAX_MAPPING (100)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IIrpQueueVtbl *lpVtbl;
|
||||
@@ -27,9 +25,10 @@ typedef struct
|
||||
LONG ref;
|
||||
|
||||
ULONG CurrentOffset;
|
||||
ULONG NextMapping;
|
||||
LONG NumMappings;
|
||||
IN KSPIN_CONNECT *ConnectDetails;
|
||||
ULONG NumDataAvailable;
|
||||
KSPIN_CONNECT *ConnectDetails;
|
||||
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
||||
|
||||
KDPC Dpc;
|
||||
PIRP_MAPPING FirstMap;
|
||||
@@ -38,7 +37,7 @@ typedef struct
|
||||
ULONG DpcActive;
|
||||
PIRP_MAPPING FreeMapHead;
|
||||
PIRP_MAPPING FreeMapTail;
|
||||
|
||||
ULONG FreeDataSize;
|
||||
LONG FreeCount;
|
||||
|
||||
}IIrpQueueImpl;
|
||||
@@ -63,20 +62,27 @@ DpcRoutine(
|
||||
{
|
||||
NextMapping = CurMapping->Next;
|
||||
|
||||
CurMapping->Irp->IoStatus.Information = CurMapping->Header->DataUsed;
|
||||
CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
|
||||
This->FreeDataSize -= CurMapping->Header->DataUsed;
|
||||
|
||||
if (CurMapping->Irp)
|
||||
{
|
||||
CurMapping->Irp->IoStatus.Information = CurMapping->Header->DataUsed;
|
||||
CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
|
||||
}
|
||||
|
||||
ExFreePool(CurMapping->Header->Data);
|
||||
ExFreePool(CurMapping->Header);
|
||||
|
||||
ExFreePool(CurMapping);
|
||||
|
||||
CurMapping = NextMapping;
|
||||
InterlockedDecrement(&This->FreeCount);
|
||||
|
||||
Count++;
|
||||
}
|
||||
This->DpcActive = FALSE;
|
||||
DPRINT1("Freed %u Buffers / IRP\n", Count);
|
||||
DPRINT1("Freed %u Buffers / IRP Available Mappings %u\n", Count, This->NumMappings);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,11 +138,14 @@ NTAPI
|
||||
IIrpQueue_fnInit(
|
||||
IN IIrpQueue *iface,
|
||||
IN KSPIN_CONNECT *ConnectDetails,
|
||||
IN PKSDATAFORMAT DataFormat,
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
This->ConnectDetails = ConnectDetails;
|
||||
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
|
||||
|
||||
KeInitializeDpc(&This->Dpc, DpcRoutine, (PVOID)This);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -161,6 +170,8 @@ IIrpQueue_fnAddMapping(
|
||||
Mapping->Irp = Irp;
|
||||
Mapping->Next = NULL;
|
||||
|
||||
DPRINT1("FirstMap %p LastMap %p NumMappings %u\n", This->FirstMap, This->LastMap, This->NumMappings);
|
||||
|
||||
if (!This->FirstMap)
|
||||
This->FirstMap = Mapping;
|
||||
else
|
||||
@@ -170,8 +181,16 @@ IIrpQueue_fnAddMapping(
|
||||
|
||||
InterlockedIncrement(&This->NumMappings);
|
||||
|
||||
DPRINT1("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu\n", This->NumMappings, Mapping->Header->DataUsed);
|
||||
if (Irp)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_PENDING;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoMarkIrpPending(Irp);
|
||||
}
|
||||
|
||||
This->NumDataAvailable += Mapping->Header->DataUsed;
|
||||
|
||||
DPRINT1("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu NumDataAvailable %lu\n", This->NumMappings, Mapping->Header->DataUsed, This->NumDataAvailable);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -221,8 +240,13 @@ IIrpQueue_fnUpdateMapping(
|
||||
|
||||
This->FreeMapTail = Mapping;
|
||||
Mapping->Next = NULL;
|
||||
This->FreeDataSize += Mapping->Header->DataUsed;
|
||||
InterlockedDecrement(&This->NumMappings);
|
||||
This->NumDataAvailable -= Mapping->Header->DataUsed;
|
||||
|
||||
if (This->FreeCount > iface->lpVtbl->MinMappings(iface) && This->DpcActive == FALSE)
|
||||
|
||||
if ((This->FreeDataSize > This->DataFormat->WaveFormatEx.nAvgBytesPerSec || This->FreeCount > 25) &&
|
||||
This->DpcActive == FALSE)
|
||||
{
|
||||
Mapping = This->FreeMapHead;
|
||||
This->FreeMapHead = NULL;
|
||||
@@ -243,22 +267,33 @@ IIrpQueue_fnNumMappings(
|
||||
return This->NumMappings;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IIrpQueue_fnMaxMappings(
|
||||
IN IIrpQueue *iface)
|
||||
{
|
||||
return MAX_MAPPING;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IIrpQueue_fnMinMappings(
|
||||
IN IIrpQueue *iface)
|
||||
{
|
||||
return MAX_MAPPING / 4;
|
||||
return 25;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
IIrpQueue_fnMinimumDataAvailable(
|
||||
IN IIrpQueue *iface)
|
||||
{
|
||||
BOOL Result;
|
||||
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
|
||||
|
||||
if (This->DataFormat->WaveFormatEx.nAvgBytesPerSec < This->NumDataAvailable)
|
||||
Result = TRUE;
|
||||
else
|
||||
Result = FALSE;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static IIrpQueueVtbl vt_IIrpQueue =
|
||||
{
|
||||
IIrpQueue_fnQueryInterface,
|
||||
@@ -270,7 +305,7 @@ static IIrpQueueVtbl vt_IIrpQueue =
|
||||
IIrpQueue_fnUpdateMapping,
|
||||
IIrpQueue_fnNumMappings,
|
||||
IIrpQueue_fnMinMappings,
|
||||
IIrpQueue_fnMaxMappings
|
||||
IIrpQueue_fnMinimumDataAvailable
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct
|
||||
ULONG ActiveIrpOffset;
|
||||
ULONG DelayedRequestInProgress;
|
||||
ULONG RetryCount;
|
||||
ULONG FrameSize;
|
||||
|
||||
}IPortPinWaveCyclicImpl;
|
||||
|
||||
@@ -172,16 +173,16 @@ IServiceSink_fnRequestService(
|
||||
|
||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
|
||||
|
||||
|
||||
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
This->RetryCount++;
|
||||
if (This->RetryCount > 30)
|
||||
{
|
||||
DPRINT1("Stopping\n");
|
||||
DPRINT1("Stopping %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||
This->RetryCount = 0;
|
||||
This->State = KSSTATE_STOP;
|
||||
return;
|
||||
}
|
||||
DPRINT("IServiceSink_fnRequestService> Waiting for mapping\n");
|
||||
@@ -380,7 +381,10 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||
|
||||
if (This->Stream)
|
||||
{
|
||||
Status = This->Stream->lpVtbl->SetFormat(This->Stream, DataFormat);
|
||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||
This->State = KSSTATE_STOP;
|
||||
|
||||
Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (This->Format)
|
||||
@@ -646,27 +650,46 @@ IPortPinWaveCyclic_fnFastWrite(
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONTEXT_WRITE Packet;
|
||||
PIRP Irp;
|
||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||
|
||||
DPRINT1("IPortPinWaveCyclic_fnFastWrite entered\n");
|
||||
|
||||
Packet = (PCONTEXT_WRITE)Buffer;
|
||||
|
||||
//if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
||||
// Irp = Packet->Irp;
|
||||
//else
|
||||
Irp = NULL;
|
||||
|
||||
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Packet->Irp);
|
||||
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
return FALSE;
|
||||
|
||||
if ((This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) > This->IrpQueue->lpVtbl->MinMappings(This->IrpQueue)) &&
|
||||
This->State != KSSTATE_RUN)
|
||||
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN)
|
||||
{
|
||||
/* some should initiate a state request but didnt do it */
|
||||
DPRINT1("Starting stream with %lu mappings\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
||||
|
||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN);
|
||||
This->State = KSSTATE_RUN;
|
||||
}
|
||||
|
||||
if (!Irp)
|
||||
{
|
||||
DPRINT1("Completing Irp %p\n", Packet->Irp);
|
||||
|
||||
Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Packet->Irp->IoStatus.Information = Packet->Header.DataUsed;
|
||||
IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
|
||||
StatusBlock->Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusBlock->Status = STATUS_PENDING;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -697,13 +720,6 @@ IPortPinWaveCyclic_fnInit(
|
||||
|
||||
DeviceObject = GetDeviceObject(Port);
|
||||
|
||||
|
||||
Status = NewIrpQueue(&This->IrpQueue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DeviceObject);
|
||||
|
||||
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
|
||||
|
||||
DPRINT("IPortPinWaveCyclic_fnInit entered\n");
|
||||
@@ -714,6 +730,12 @@ IPortPinWaveCyclic_fnInit(
|
||||
|
||||
RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
|
||||
|
||||
Status = NewIrpQueue(&This->IrpQueue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject);
|
||||
|
||||
Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
|
||||
&This->Stream,
|
||||
NULL,
|
||||
@@ -729,7 +751,7 @@ IPortPinWaveCyclic_fnInit(
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
|
||||
Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
|
||||
(PSERVICESINK)&This->lpVtblServiceSink);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
@@ -743,6 +765,8 @@ IPortPinWaveCyclic_fnInit(
|
||||
This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel);
|
||||
This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
|
||||
|
||||
//Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -733,10 +733,8 @@ WdmAudWrite(
|
||||
|
||||
KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, KernelMode);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_PENDING;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoMarkIrpPending(Irp);
|
||||
return STATUS_PENDING;
|
||||
|
||||
return IoStatusBlock.Status;
|
||||
|
||||
//return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ CreatePinWorkerRoutine(
|
||||
else
|
||||
{
|
||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE;
|
||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = NULL;
|
||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = VirtualPinHandle;
|
||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
|
||||
}
|
||||
|
||||
@@ -411,6 +411,43 @@ HandleSysAudioFilterPinProperties(
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
SetPinFormat(
|
||||
PKSAUDIO_DEVICE_ENTRY Entry,
|
||||
KSPIN_CONNECT * PinConnect,
|
||||
ULONG Length)
|
||||
{
|
||||
KSP_PIN PinRequest;
|
||||
PFILE_OBJECT FileObject;
|
||||
ULONG BytesReturned;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* re-using pin */
|
||||
PinRequest.Property.Set = KSPROPSETID_Connection;
|
||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
||||
PinRequest.PinId = PinConnect->PinId;
|
||||
|
||||
/* get pin file object */
|
||||
Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get pin file object with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY),
|
||||
(PVOID)(PinConnect + 1), Length, &BytesReturned);
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
HandleSysAudioFilterPinCreation(
|
||||
PIRP Irp,
|
||||
@@ -429,9 +466,9 @@ HandleSysAudioFilterPinCreation(
|
||||
NTSTATUS Status;
|
||||
KSPIN_CINSTANCES PinInstances;
|
||||
PIO_WORKITEM WorkItem;
|
||||
PFILE_OBJECT FileObject;
|
||||
PPIN_WORKER_CONTEXT WorkerContext;
|
||||
PDISPATCH_CONTEXT DispatchContext;
|
||||
ULONG Index, SubIndex;
|
||||
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
@@ -456,8 +493,7 @@ HandleSysAudioFilterPinCreation(
|
||||
|
||||
/* get client context */
|
||||
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
|
||||
if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs ||
|
||||
ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId != InstanceInfo->DeviceNumber)
|
||||
if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs)
|
||||
{
|
||||
/* we have a problem */
|
||||
KeBugCheckEx(0, 0, 0, 0, 0);
|
||||
@@ -506,6 +542,30 @@ HandleSysAudioFilterPinCreation(
|
||||
|
||||
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
||||
{
|
||||
for (Index = 0; Index < ClientInfo->NumDevices; Index++)
|
||||
{
|
||||
if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber)
|
||||
{
|
||||
if (ClientInfo->Devs[Index].ClientHandlesCount)
|
||||
{
|
||||
for(SubIndex = 0; SubIndex < ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++)
|
||||
{
|
||||
if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId == PinConnect->PinId)
|
||||
{
|
||||
/* reuse opened pin */
|
||||
Length = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||
Status = SetPinFormat(Entry, PinConnect, Length);
|
||||
DPRINT1("Reusing instance handle Status %x\n", Status);
|
||||
ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE);
|
||||
*((PHANDLE)Irp->UserBuffer) = ClientInfo->Devs[Index].ClientHandles[SubIndex].hPin;
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(HANDLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* pin already exists */
|
||||
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
|
||||
if (Entry->Pins[PinConnect->PinId].References > 1)
|
||||
@@ -550,39 +610,14 @@ HandleSysAudioFilterPinCreation(
|
||||
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
||||
{
|
||||
/* re-using pin */
|
||||
PinRequest.Property.Set = KSPROPSETID_Connection;
|
||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
||||
|
||||
/* get pin file object */
|
||||
Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||
|
||||
Status = SetPinFormat(Entry, PinConnect, Length);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get pin file object with %x\n", Status);
|
||||
IoFreeWorkItem(WorkItem);
|
||||
ExFreePool(WorkerContext);
|
||||
ExFreePool(DispatchContext);
|
||||
return SetIrpIoStatus(Irp, Status, 0);
|
||||
}
|
||||
|
||||
Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY),
|
||||
(PVOID)(PinConnect + 1), Length, &BytesReturned);
|
||||
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to set format with Status %x\n", Status);
|
||||
IoFreeWorkItem(WorkItem);
|
||||
ExFreePool(WorkerContext);
|
||||
ExFreePool(DispatchContext);
|
||||
return SetIrpIoStatus(Irp, Status, 0);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user