- Check in wdmaud if a pin with the specified filter id and pin id has been opened

- Partly rewrite SysAudio as it is no longer required to store client specific information per connection since wdmaud just opens one connection
- Verify all audio handles at incoming irp

svn path=/trunk/; revision=41371
This commit is contained in:
Johannes Anderwald 2009-06-10 18:28:15 +00:00
parent 305a63335d
commit a0aa8829fc
6 changed files with 134 additions and 320 deletions

View file

@ -165,6 +165,17 @@ WdmAudControlOpen(
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* close pin handle which uses same virtual audio device id and pin id */
for(Index = 0; Index < ClientInfo->NumPins; Index++)
{
if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle)
{
ZwClose(ClientInfo->hPins[Index].Handle);
ClientInfo->hPins[Index].Handle = NULL;
}
}
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
InstanceInfo = ExAllocatePool(NonPagedPool, Length);
if (!InstanceInfo)
@ -272,6 +283,8 @@ WdmAudControlOpen(
ClientInfo->hPins = Handels;
ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle;
ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceInfo->DeviceType;
ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId;
ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId;
ClientInfo->NumPins++;
}
DeviceInfo->hDevice = PinHandle;

View file

@ -16,6 +16,8 @@ typedef struct
{
HANDLE Handle;
SOUND_DEVICE_TYPE Type;
ULONG FilterId;
ULONG PinId;
}WDMAUD_HANDLE, *PWDMAUD_HANDLE;

View file

@ -169,7 +169,6 @@ SysAudioOpenVirtualDevice(
IN ULONG DeviceNumber,
PSYSAUDIODEVEXT DeviceExtension)
{
PSYSAUDIO_CLIENT ClientInfo;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
PKSOBJECT_CREATE_ITEM CreateItem;
@ -183,19 +182,6 @@ SysAudioOpenVirtualDevice(
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
/* get client context */
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
/* sanity check */
ASSERT(ClientInfo);
/* check for valid device index */
if (DeviceNumber >= ClientInfo->NumDevices)
{
/* invalid device index */
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
/* get device context */
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
ASSERT(Entry != NULL);
@ -249,8 +235,7 @@ CreateMixerPinAndSetFormat(
IN KSPIN_CONNECT *PinConnect,
IN PKSDATAFORMAT InputFormat,
IN PKSDATAFORMAT OutputFormat,
OUT PHANDLE MixerPinHandle,
OUT PFILE_OBJECT *MixerFileObject)
OUT PHANDLE MixerPinHandle)
{
NTSTATUS Status;
HANDLE PinHandle;
@ -281,8 +266,9 @@ CreateMixerPinAndSetFormat(
ZwClose(PinHandle);
}
ObDereferenceObject(FileObject);
*MixerPinHandle = PinHandle;
*MixerFileObject = FileObject;
return Status;
}
@ -294,11 +280,8 @@ CreatePinWorkerRoutine(
IN PVOID Context)
{
NTSTATUS Status;
ULONG NumHandels;
HANDLE RealPinHandle = NULL, VirtualPinHandle = NULL, Filter;
PFILE_OBJECT RealFileObject = NULL, VirtualFileObject = NULL;
PSYSAUDIO_CLIENT AudioClient;
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
PFILE_OBJECT VirtualFileObject = NULL;
PKSDATAFORMAT_WAVEFORMATEX InputFormat;
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
PKSPIN_CONNECT MixerPinConnect = NULL;
@ -374,28 +357,12 @@ CreatePinWorkerRoutine(
}
}
/* get pin file object */
Status = ObReferenceObjectByHandle(RealPinHandle,
GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get file object with %x\n", Status);
goto cleanup;
}
if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1)
{
/* store the pin handle there if the pin can only be instantiated once*/
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
}
ASSERT(WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount);
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0;
WorkerContext->DispatchContext->Handle = RealPinHandle;
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry;
WorkerContext->DispatchContext->FileObject = RealFileObject;
/* Do we need to transform the audio stream */
if (OutputFormat != NULL)
@ -405,8 +372,7 @@ CreatePinWorkerRoutine(
MixerPinConnect,
(PKSDATAFORMAT)InputFormat,
(PKSDATAFORMAT)OutputFormat,
&WorkerContext->DispatchContext->hMixerPin,
&WorkerContext->DispatchContext->MixerFileObject);
&WorkerContext->DispatchContext->hMixerPin);
if (!NT_SUCCESS(Status))
@ -438,61 +404,21 @@ CreatePinWorkerRoutine(
goto cleanup;
}
ASSERT(WorkerContext->AudioClient);
ASSERT(WorkerContext->AudioClient->NumDevices > 0);
ASSERT(WorkerContext->AudioClient->Devs != NULL);
ASSERT(WorkerContext->Entry->Pins != NULL);
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
AudioClient = WorkerContext->AudioClient;
NumHandels = AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount;
/* increment reference count */
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
ClientPinHandle = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_PIN_HANDLE) * (NumHandels+1));
if (ClientPinHandle)
{
if (NumHandels)
{
ASSERT(AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles != NULL);
RtlMoveMemory(ClientPinHandle,
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles,
sizeof(SYSAUDIO_PIN_HANDLE) * NumHandels);
ExFreePool(AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles);
}
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles = ClientPinHandle;
/// if the pin can be instantiated more than once
/// then store the real pin handle in the client context
/// otherwise just the pin id of the available pin
if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount > 1)
{
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = TRUE;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = RealPinHandle;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext;
}
else
{
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = VirtualPinHandle;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin;
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext;
}
/// increase reference count
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++;
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
}
else
{
/* no memory */
goto cleanup;
}
/* store the pin handle there if the pin can only be instantiated once*/
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = VirtualPinHandle;
/* store pin context */
VirtualFileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
/* release virtual file object */
ObDereferenceObject(VirtualFileObject);
DPRINT("Successfully created virtual pin %p\n", VirtualPinHandle);
*((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
@ -502,15 +428,9 @@ CreatePinWorkerRoutine(
return;
cleanup:
if (RealFileObject)
ObDereferenceObject(RealFileObject);
if (RealPinHandle)
ZwClose(RealPinHandle);
if (WorkerContext->DispatchContext->MixerFileObject)
ObDereferenceObject(WorkerContext->DispatchContext->MixerFileObject);
if (WorkerContext->DispatchContext->hMixerPin)
ZwClose(WorkerContext->DispatchContext->hMixerPin);
@ -767,51 +687,6 @@ GetPinInstanceCount(
}
VOID
CloseExistingPin(
PSYSAUDIO_CLIENT ClientInfo,
PSYSAUDIO_INSTANCE_INFO InstanceInfo,
PKSPIN_CONNECT PinConnect)
{
ULONG Index, SubIndex;
PDISPATCH_CONTEXT DispatchContext;
/* scan the clientinfo if the client has already opened device with the specified pin */
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)
{
/* the pin has been already opened by the client, re-use it */
ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE);
DispatchContext = ClientInfo->Devs[Index].ClientHandles[SubIndex].DispatchContext;
if (DispatchContext->MixerFileObject)
ObDereferenceObject(DispatchContext->MixerFileObject);
if (DispatchContext->hMixerPin)
ZwClose(DispatchContext->hMixerPin);
if (DispatchContext->FileObject)
ObDereferenceObject(DispatchContext->FileObject);
if (DispatchContext->Handle)
ZwClose(DispatchContext->Handle);
ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId = (ULONG)-1;
}
}
}
}
}
}
NTSTATUS
HandleSysAudioFilterPinCreation(
PIRP Irp,
@ -824,7 +699,6 @@ HandleSysAudioFilterPinCreation(
KSPIN_CONNECT * PinConnect;
PIO_STACK_LOCATION IoStack;
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
PSYSAUDIO_CLIENT ClientInfo;
PKSOBJECT_CREATE_ITEM CreateItem;
NTSTATUS Status;
KSPIN_CINSTANCES PinInstances;
@ -853,14 +727,6 @@ HandleSysAudioFilterPinCreation(
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
/* get client context */
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs)
{
/* we have a problem */
KeBugCheckEx(0, 0, 0, 0, 0);
}
/* get sysaudio entry */
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, InstanceInfo->DeviceNumber);
if (!Entry)
@ -884,9 +750,6 @@ HandleSysAudioFilterPinCreation(
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
/* close existing pin first */
CloseExistingPin(ClientInfo, InstanceInfo, PinConnect);
/* query instance count */
Status = GetPinInstanceCount(Entry, &PinInstances, PinConnect);
if (!NT_SUCCESS(Status))
@ -905,14 +768,11 @@ HandleSysAudioFilterPinCreation(
{
/* pin already exists */
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
if (Entry->Pins[PinConnect->PinId].References)
{
/* FIXME need ksmixer */
DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, Entry->Pins[PinConnect->PinId].References);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
}
ASSERT(Entry->Pins[PinConnect->PinId].References);
DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, Entry->Pins[PinConnect->PinId].References);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* create dispatch pin context */
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
if (!DispatchContext)
@ -956,7 +816,6 @@ HandleSysAudioFilterPinCreation(
WorkerContext->Entry = Entry;
WorkerContext->Irp = Irp;
WorkerContext->PinConnect = PinConnect;
WorkerContext->AudioClient = ClientInfo;
WorkerContext->DeviceExtension = DeviceExtension;
WorkerContext->WorkItem = WorkItem;

View file

@ -73,79 +73,7 @@ Dispatch_fnClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PSYSAUDIO_CLIENT Client;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
PIO_STACK_LOCATION IoStatus;
ULONG Index, SubIndex;
PSYSAUDIODEVEXT DeviceExtension;
PDISPATCH_CONTEXT DispatchContext;
IoStatus = IoGetCurrentIrpStackLocation(Irp);
Client = (PSYSAUDIO_CLIENT)IoStatus->FileObject->FsContext2;
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
DPRINT("Client %p NumDevices %u\n", Client, Client->NumDevices);
for(Index = 0; Index < Client->NumDevices; Index++)
{
DPRINT("Index %u Device %u Handels Count %u\n", Index, Client->Devs[Index].DeviceId, Client->Devs[Index].ClientHandlesCount);
if (Client->Devs[Index].ClientHandlesCount)
{
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Client->Devs[Index].DeviceId);
ASSERT(Entry != NULL);
for(SubIndex = 0; SubIndex < Client->Devs[Index].ClientHandlesCount; SubIndex++)
{
if (Client->Devs[Index].ClientHandles[SubIndex].PinId == (ULONG)-1)
continue;
if (Client->Devs[Index].ClientHandles[SubIndex].bHandle)
{
DPRINT("Closing handle %p\n", Client->Devs[Index].ClientHandles[SubIndex].hPin);
ZwClose(Client->Devs[Index].ClientHandles[SubIndex].hPin);
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
}
else
{
/* this is a pin which can only be instantiated once
* so we just need to release the reference count on that pin
*/
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
DispatchContext = (PDISPATCH_CONTEXT)Client->Devs[Index].ClientHandles[SubIndex].DispatchContext;
if (DispatchContext->MixerFileObject)
ObDereferenceObject(DispatchContext->MixerFileObject);
if (DispatchContext->hMixerPin)
ZwClose(DispatchContext->hMixerPin);
if (DispatchContext->FileObject)
ObDereferenceObject(DispatchContext->FileObject);
ExFreePool(DispatchContext);
DPRINT("Index %u DeviceIndex %u Pin %u References %u\n", Index, Client->Devs[Index].DeviceId, SubIndex, Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References);
if (!Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References)
{
DPRINT("Closing pin %p\n", Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle);
ZwClose(Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle);
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle = NULL;
}
}
}
ExFreePool(Client->Devs[Index].ClientHandles);
}
}
if (Client->Devs)
ExFreePool(Client->Devs);
ExFreePool(Client);
DPRINT("Dispatch_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
@ -259,13 +187,10 @@ DispatchCreateSysAudio(
{
NTSTATUS Status;
KSOBJECT_HEADER ObjectHeader;
PSYSAUDIO_CLIENT Client;
PKSOBJECT_CREATE_ITEM CreateItem;
PIO_STACK_LOCATION IoStatus;
LPWSTR Buffer;
PSYSAUDIODEVEXT DeviceExtension;
ULONG Index;
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
IoStatus = IoGetCurrentIrpStackLocation(Irp);
@ -298,59 +223,15 @@ DispatchCreateSysAudio(
return STATUS_INSUFFICIENT_RESOURCES;
}
Client = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT));
if (!Client)
{
ExFreePool(CreateItem);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* get device extension */
DeviceExtension = (PSYSAUDIODEVEXT) DeviceObject->DeviceExtension;
Client->NumDevices = DeviceExtension->NumberOfKsAudioDevices;
/* has sysaudio found any devices */
if (Client->NumDevices)
{
Client->Devs = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT_HANDELS) * Client->NumDevices);
if (!Client->Devs)
{
ExFreePool(CreateItem);
ExFreePool(Client);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
else
{
/* no devices yet available */
Client->Devs = NULL;
}
/* Initialize devs array */
for(Index = 0; Index < Client->NumDevices; Index++)
{
Client->Devs[Index].DeviceId = Index;
Client->Devs[Index].ClientHandles = NULL;
Client->Devs[Index].ClientHandlesCount = 0;
}
/* zero create struct */
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
/* store create context */
CreateItem->Context = (PVOID)Client;
RtlInitUnicodeString(&CreateItem->ObjectClass, L"SysAudio");
/* store the object in FsContext */
IoStatus->FileObject->FsContext2 = (PVOID)Client;
/* allocate object header */
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);

View file

@ -17,6 +17,7 @@ Pin_fnDeviceIoControl(
PDISPATCH_CONTEXT Context;
NTSTATUS Status;
ULONG BytesReturned;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION IoStack;
DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
@ -29,15 +30,27 @@ Pin_fnDeviceIoControl(
/* Sanity check */
ASSERT(Context);
ASSERT(Context->FileObject != NULL);
/* acquire real pin file object */
Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
/* Complete the irp */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* Re-dispatch the request to the real target pin */
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
IoStack->Parameters.DeviceIoControl.InputBufferLength,
Irp->UserBuffer,
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
&BytesReturned);
/* release file object */
ObDereferenceObject(FileObject);
/* Save status and information */
Irp->IoStatus.Information = BytesReturned;
@ -57,6 +70,7 @@ Pin_fnRead(
PDISPATCH_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
ULONG BytesReturned;
PFILE_OBJECT FileObject;
NTSTATUS Status;
/* Get current stack location */
@ -67,17 +81,30 @@ Pin_fnRead(
/* Sanity check */
ASSERT(Context);
ASSERT(Context->FileObject != NULL);
/* acquire real pin file object */
Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
/* Complete the irp */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* Re-dispatch the request to the real target pin */
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_READ_STREAM,
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_READ_STREAM,
MmGetMdlVirtualAddress(Irp->MdlAddress),
IoStack->Parameters.Read.Length,
NULL,
0,
&BytesReturned);
if (Context->hMixerPin && Context->MixerFileObject)
/* release file object */
ObDereferenceObject(FileObject);
if (Context->hMixerPin)
{
// FIXME
// call kmixer to convert stream
@ -102,6 +129,7 @@ Pin_fnWrite(
PDISPATCH_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
ULONG BytesReturned;
PFILE_OBJECT FileObject;
NTSTATUS Status;
/* Get current stack location */
@ -112,24 +140,36 @@ Pin_fnWrite(
/* Sanity check */
ASSERT(Context);
ASSERT(Context->FileObject != NULL);
if (Context->hMixerPin && Context->MixerFileObject)
if (Context->hMixerPin)
{
// FIXME
// call kmixer to convert stream
UNIMPLEMENTED
}
/* acquire real pin file object */
Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
/* Complete the irp */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* Re-dispatch the request to the real target pin */
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
MmGetMdlVirtualAddress(Irp->MdlAddress),
IoStack->Parameters.Read.Length,
NULL,
0,
&BytesReturned);
/* release file object */
ObDereferenceObject(FileObject);
/* Save status and information */
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
@ -149,6 +189,7 @@ Pin_fnFlush(
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT PinDeviceObject;
PIRP PinIrp;
PFILE_OBJECT FileObject;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
@ -161,10 +202,24 @@ Pin_fnFlush(
/* Sanity check */
ASSERT(Context);
ASSERT(Context->FileObject != NULL);
/* acquire real pin file object */
Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
/* Complete the irp */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* Get Pin's device object */
PinDeviceObject = IoGetRelatedDeviceObject(Context->FileObject);
PinDeviceObject = IoGetRelatedDeviceObject(FileObject);
/* release file object */
ObDereferenceObject(FileObject);
/* Initialize notification event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
@ -177,7 +232,7 @@ Pin_fnFlush(
/* Get the next stack location */
IoStack = IoGetNextIrpStackLocation(PinIrp);
/* The file object must be present in the irp as it contains the KSOBJECT_HEADER */
IoStack->FileObject = Context->FileObject;
IoStack->FileObject = FileObject;
/* call the driver */
Status = IoCallDriver(PinDeviceObject, PinIrp);
@ -206,8 +261,25 @@ Pin_fnClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDISPATCH_CONTEXT Context;
PIO_STACK_LOCATION IoStack;
DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
/* Get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* The dispatch context is stored in the FsContext2 member */
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
if (Context->Handle)
{
ZwClose(Context->Handle);
}
ZwClose(Context->hMixerPin);
ExFreePool(Context);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@ -294,15 +366,22 @@ Pin_fnFastWrite(
PDEVICE_OBJECT DeviceObject)
{
PDISPATCH_CONTEXT Context;
PFILE_OBJECT RealFileObject;
NTSTATUS Status;
DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
Context = (PDISPATCH_CONTEXT)FileObject->FsContext2;
if (Context->hMixerPin && Context->MixerFileObject)
if (Context->hMixerPin)
{
Status = KsStreamIo(Context->MixerFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
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);
ObDereferenceObject(RealFileObject);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Mixing stream failed with %lx\n", Status);
@ -310,7 +389,14 @@ Pin_fnFastWrite(
}
}
Status = KsStreamIo(Context->FileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
if (!NT_SUCCESS(Status))
return FALSE;
Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
ObDereferenceObject(RealFileObject);
if (Status == STATUS_SUCCESS)
return TRUE;
else

View file

@ -11,30 +11,6 @@
#include <debug.h>
#include <stdio.h>
typedef struct
{
BOOL bHandle; // indicates if an audio pin can be instantated more than once
ULONG PinId; // specifies the pin id
HANDLE hPin; // handle to audio irp pin
HANDLE hMixer; // handle to mixer pin
PVOID DispatchContext; // pointer to dispatch context
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
typedef struct
{
ULONG DeviceId; //specifies the device id
ULONG ClientHandlesCount; // number of client handles
PSYSAUDIO_PIN_HANDLE ClientHandles; // array of client handles
}SYSAUDIO_CLIENT_HANDELS, *PSYSAUDIO_CLIENT_HANDELS;
typedef struct
{
ULONG NumDevices; // number of devices in Devs array
PSYSAUDIO_CLIENT_HANDELS Devs; // array of client handles
}SYSAUDIO_CLIENT, *PSYSAUDIO_CLIENT;
typedef struct
{
ULONG MaxPinInstanceCount; // maximum times a audio irp pin can be instantiated
@ -94,12 +70,10 @@ typedef struct
typedef struct
{
HANDLE Handle; // audio irp pin handle
PFILE_OBJECT FileObject; // audio irp pin file object
ULONG PinId; // pin id of device
PKSAUDIO_SUBDEVICE_ENTRY AudioEntry; // pointer to audio device entry
HANDLE hMixerPin; // handle to mixer pin
PFILE_OBJECT MixerFileObject; // mixer file object
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
// struct PIN_WORKER_CONTEXT
@ -115,7 +89,6 @@ typedef struct
PKSAUDIO_SUBDEVICE_ENTRY Entry;
KSPIN_CONNECT * PinConnect;
PDISPATCH_CONTEXT DispatchContext;
PSYSAUDIO_CLIENT AudioClient;
PSYSAUDIODEVEXT DeviceExtension;
PKSDATAFORMAT_WAVEFORMATEX MixerFormat;
PIO_WORKITEM WorkItem;