mirror of
https://github.com/reactos/reactos.git
synced 2025-06-11 04:47:22 +00:00
- Export KsNullDriverUnload
- Stop the audio stream at PASSIVE_LEVEL - Refactor sysaudio code to make it less complex and remove code which is not used - Add a few comments svn path=/trunk/; revision=40238
This commit is contained in:
parent
bf2b5adf8e
commit
5a37c1fdad
9 changed files with 310 additions and 240 deletions
|
@ -98,7 +98,7 @@
|
||||||
@ stdcall KsFreeObjectCreateItem(ptr ptr)
|
@ stdcall KsFreeObjectCreateItem(ptr ptr)
|
||||||
@ stdcall KsFreeObjectCreateItemsByContext(ptr ptr)
|
@ stdcall KsFreeObjectCreateItemsByContext(ptr ptr)
|
||||||
@ stdcall KsLoadResource(ptr long ptr long ptr ptr)
|
@ stdcall KsLoadResource(ptr long ptr long ptr ptr)
|
||||||
; KsNullDriverUnload@4
|
@ stdcall KsNullDriverUnload(ptr)
|
||||||
@ stdcall KsPinDataIntersectionEx(ptr ptr ptr long ptr long ptr ptr)
|
@ stdcall KsPinDataIntersectionEx(ptr ptr ptr long ptr long ptr ptr)
|
||||||
@ stdcall KsQueryDevicePnpObject(ptr)
|
@ stdcall KsQueryDevicePnpObject(ptr)
|
||||||
@ stdcall KsRecalculateStackDepth(ptr long)
|
@ stdcall KsRecalculateStackDepth(ptr long)
|
||||||
|
|
|
@ -165,7 +165,7 @@ KsLoadResource(
|
||||||
/*
|
/*
|
||||||
@unimplemented
|
@unimplemented
|
||||||
*/
|
*/
|
||||||
VOID
|
KSDDKAPI VOID NTAPI
|
||||||
KsNullDriverUnload(
|
KsNullDriverUnload(
|
||||||
IN PDRIVER_OBJECT DriverObject)
|
IN PDRIVER_OBJECT DriverObject)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ typedef struct
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
PKSDATAFORMAT Format;
|
PKSDATAFORMAT Format;
|
||||||
KSPIN_CONNECT * ConnectDetails;
|
KSPIN_CONNECT * ConnectDetails;
|
||||||
|
KDPC Dpc;
|
||||||
|
|
||||||
PVOID CommonBuffer;
|
PVOID CommonBuffer;
|
||||||
ULONG CommonBufferSize;
|
ULONG CommonBufferSize;
|
||||||
|
@ -183,6 +184,42 @@ UpdateCommonBufferOverlap(
|
||||||
UpdateCommonBuffer(This, Position);
|
UpdateCommonBuffer(This, Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
StopStreamWorkerRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)Context;
|
||||||
|
|
||||||
|
DPRINT1("Stopping %u Irql %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), KeGetCurrentIrql());
|
||||||
|
|
||||||
|
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||||
|
This->State = KSSTATE_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
StopStreamRoutine(
|
||||||
|
IN PKDPC Dpc,
|
||||||
|
IN PVOID DeferredContext,
|
||||||
|
IN PVOID SystemArgument1,
|
||||||
|
IN PVOID SystemArgument2)
|
||||||
|
{
|
||||||
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)DeferredContext;
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
|
||||||
|
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WorkItem = IoAllocateWorkItem(GetDeviceObject(This->Port));
|
||||||
|
if (!WorkItem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IoQueueWorkItem(WorkItem, StopStreamWorkerRoutine, DelayedWorkQueue, (PVOID)This);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
|
@ -194,32 +231,18 @@ IServiceSink_fnRequestService(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer;
|
||||||
ULONG BufferSize;
|
ULONG BufferSize;
|
||||||
|
|
||||||
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
|
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (!This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue))
|
KeInsertQueueDpc(&This->Dpc, NULL, NULL);
|
||||||
{
|
|
||||||
/* there is an active dpc pending
|
|
||||||
* wait untill this dpc is done, in order to complete the remaining irps
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DPRINT1("Stopping %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
|
||||||
|
|
||||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
|
||||||
This->State = KSSTATE_STOP;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KeGetCurrentIrql() == DISPATCH_LEVEL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
|
Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
|
||||||
DPRINT("Position %u BufferSize %u ActiveIrpOffset %u\n", Position, This->CommonBufferSize, BufferSize);
|
DPRINT1("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u\n", Position, Buffer, This->CommonBufferSize, BufferSize);
|
||||||
|
|
||||||
if (Position < This->CommonBufferOffset)
|
if (Position < This->CommonBufferOffset)
|
||||||
{
|
{
|
||||||
|
@ -836,6 +859,7 @@ IPortPinWaveCyclic_fnInit(
|
||||||
This->KsPinDescriptor = KsPinDescriptor;
|
This->KsPinDescriptor = KsPinDescriptor;
|
||||||
This->ConnectDetails = ConnectDetails;
|
This->ConnectDetails = ConnectDetails;
|
||||||
This->Miniport = GetWaveCyclicMiniport(Port);
|
This->Miniport = GetWaveCyclicMiniport(Port);
|
||||||
|
KeInitializeDpc(&This->Dpc, StopStreamRoutine, (PVOID)This);
|
||||||
|
|
||||||
DeviceObject = GetDeviceObject(Port);
|
DeviceObject = GetDeviceObject(Port);
|
||||||
|
|
||||||
|
@ -904,7 +928,7 @@ IPortPinWaveCyclic_fnInit(
|
||||||
This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
|
This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
|
||||||
This->Capture = Capture;
|
This->Capture = Capture;
|
||||||
|
|
||||||
//Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10, &This->FrameSize);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,6 @@ SysAudioOpenVirtualDevice(
|
||||||
IN ULONG DeviceNumber,
|
IN ULONG DeviceNumber,
|
||||||
PSYSAUDIODEVEXT DeviceExtension)
|
PSYSAUDIODEVEXT DeviceExtension)
|
||||||
{
|
{
|
||||||
PSYSAUDIO_CLIENT_HANDELS Index;
|
|
||||||
ULONG Count;
|
|
||||||
PSYSAUDIO_CLIENT ClientInfo;
|
PSYSAUDIO_CLIENT ClientInfo;
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
@ -83,66 +81,26 @@ SysAudioOpenVirtualDevice(
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
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 */
|
/* get device context */
|
||||||
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
|
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
|
||||||
ASSERT(Entry != NULL);
|
ASSERT(Entry != NULL);
|
||||||
|
|
||||||
/* get client context */
|
|
||||||
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
|
|
||||||
/* does the client already use a device */
|
|
||||||
if (!ClientInfo->NumDevices)
|
|
||||||
{
|
|
||||||
/* first device to be openend */
|
|
||||||
ClientInfo->Devs = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT_HANDELS));
|
|
||||||
if (!ClientInfo->Devs)
|
|
||||||
{
|
|
||||||
/* no memory */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientInfo->NumDevices = 1;
|
|
||||||
ClientInfo->Devs[0].DeviceId = DeviceNumber;
|
|
||||||
ClientInfo->Devs[0].ClientHandles = NULL;
|
|
||||||
ClientInfo->Devs[0].ClientHandlesCount = 0;
|
|
||||||
/* increase usage count */
|
|
||||||
Entry->NumberOfClients++;
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if device has already been openend */
|
|
||||||
for(Count = 0; Count < ClientInfo->NumDevices; Count++)
|
|
||||||
{
|
|
||||||
if (ClientInfo->Devs[Count].DeviceId == DeviceNumber)
|
|
||||||
{
|
|
||||||
/* device has already been opened */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* new device to be openend */
|
|
||||||
Index = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT_HANDELS) * (ClientInfo->NumDevices + 1));
|
|
||||||
if (!Index)
|
|
||||||
{
|
|
||||||
/* no memory */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClientInfo->NumDevices)
|
|
||||||
{
|
|
||||||
/* copy device count array */
|
|
||||||
RtlMoveMemory(Index, ClientInfo->Devs, ClientInfo->NumDevices * sizeof(SYSAUDIO_CLIENT_HANDELS));
|
|
||||||
}
|
|
||||||
|
|
||||||
Index[ClientInfo->NumDevices].DeviceId = DeviceNumber;
|
|
||||||
Index[ClientInfo->NumDevices].ClientHandlesCount = 0;
|
|
||||||
Index[ClientInfo->NumDevices].ClientHandles = NULL;
|
|
||||||
|
|
||||||
/* increase usage count */
|
/* increase usage count */
|
||||||
Entry->NumberOfClients++;
|
Entry->NumberOfClients++;
|
||||||
|
|
||||||
ExFreePool(ClientInfo->Devs);
|
|
||||||
|
|
||||||
ClientInfo->Devs = Index;
|
|
||||||
ClientInfo->NumDevices++;
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +320,7 @@ CreatePinWorkerRoutine(
|
||||||
|
|
||||||
if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1)
|
if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1)
|
||||||
{
|
{
|
||||||
/* store the pin handle there is the pin can only be instantiated once*/
|
/* store the pin handle there if the pin can only be instantiated once*/
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
|
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,8 +913,7 @@ SysAudioHandleProperty(
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||||
PSYSAUDIO_CLIENT ClientInfo;
|
ULONG BytesReturned;
|
||||||
ULONG Count, BytesReturned;
|
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
UNICODE_STRING GuidString;
|
UNICODE_STRING GuidString;
|
||||||
|
|
||||||
|
@ -1034,7 +991,7 @@ SysAudioHandleProperty(
|
||||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
|
||||||
{
|
{
|
||||||
/* too small buffer */
|
/* too small buffer */
|
||||||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSCOMPONENTID));
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
||||||
|
@ -1042,23 +999,6 @@ SysAudioHandleProperty(
|
||||||
Index = (PULONG)Irp->UserBuffer;
|
Index = (PULONG)Irp->UserBuffer;
|
||||||
return SysAudioOpenVirtualDevice(Irp, *Index, DeviceExtension);
|
return SysAudioOpenVirtualDevice(Irp, *Index, DeviceExtension);
|
||||||
}
|
}
|
||||||
else if (Property->Flags & KSPROPERTY_TYPE_GET)
|
|
||||||
{
|
|
||||||
Index = (PULONG)Irp->UserBuffer;
|
|
||||||
/* get client context */
|
|
||||||
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
|
|
||||||
ASSERT(ClientInfo);
|
|
||||||
/* does the client already use a device */
|
|
||||||
if (!ClientInfo->NumDevices)
|
|
||||||
{
|
|
||||||
/* no device open */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
/* store last opened device number */
|
|
||||||
*Index = ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId;
|
|
||||||
/* found no device with that device index open */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Property->Id == KSPROPERTY_SYSAUDIO_INSTANCE_INFO)
|
else if (Property->Id == KSPROPERTY_SYSAUDIO_INSTANCE_INFO)
|
||||||
{
|
{
|
||||||
|
@ -1075,28 +1015,6 @@ SysAudioHandleProperty(
|
||||||
{
|
{
|
||||||
return SysAudioOpenVirtualDevice(Irp, InstanceInfo->DeviceNumber, DeviceExtension);
|
return SysAudioOpenVirtualDevice(Irp, InstanceInfo->DeviceNumber, DeviceExtension);
|
||||||
}
|
}
|
||||||
else if (Property->Flags & KSPROPERTY_TYPE_GET)
|
|
||||||
{
|
|
||||||
/* get client context */
|
|
||||||
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
|
|
||||||
ASSERT(ClientInfo);
|
|
||||||
/* does the client already use a device */
|
|
||||||
if (!ClientInfo->NumDevices)
|
|
||||||
{
|
|
||||||
/* no device open */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
for(Count = 0; Count < ClientInfo->NumDevices; Count++)
|
|
||||||
{
|
|
||||||
if (ClientInfo->Devs[Count].DeviceId == InstanceInfo->DeviceNumber)
|
|
||||||
{
|
|
||||||
/* specified device is open */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* found no device with that device index open */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Property->Id == (ULONG)-1)
|
else if (Property->Id == (ULONG)-1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,7 +178,7 @@ DeviceInterfaceChangeCallback(
|
||||||
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
|
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
|
||||||
if (!DeviceEntry)
|
if (!DeviceEntry)
|
||||||
{
|
{
|
||||||
DPRINT1("No Mem\n");
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,14 +188,12 @@ DeviceInterfaceChangeCallback(
|
||||||
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
|
||||||
if (!DeviceEntry->DeviceName.Buffer)
|
if (!DeviceEntry->DeviceName.Buffer)
|
||||||
{
|
{
|
||||||
DPRINT1("No Mem\n");
|
|
||||||
ExFreePool(DeviceEntry);
|
ExFreePool(DeviceEntry);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\")))
|
if (!NT_SUCCESS(RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\")))
|
||||||
{
|
{
|
||||||
DPRINT1("No Mem\n");
|
|
||||||
ExFreePool(DeviceEntry->DeviceName.Buffer);
|
ExFreePool(DeviceEntry->DeviceName.Buffer);
|
||||||
ExFreePool(DeviceEntry);
|
ExFreePool(DeviceEntry);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -203,14 +201,11 @@ DeviceInterfaceChangeCallback(
|
||||||
|
|
||||||
if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, Event->SymbolicLinkName)))
|
if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, Event->SymbolicLinkName)))
|
||||||
{
|
{
|
||||||
DPRINT1("No Mem\n");
|
|
||||||
ExFreePool(DeviceEntry->DeviceName.Buffer);
|
ExFreePool(DeviceEntry->DeviceName.Buffer);
|
||||||
ExFreePool(DeviceEntry);
|
ExFreePool(DeviceEntry);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Sym %wZ\n", &DeviceEntry->DeviceName);
|
|
||||||
|
|
||||||
Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
|
Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -231,24 +226,12 @@ DeviceInterfaceChangeCallback(
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
else if (IsEqualGUIDAligned(&Event->Event,
|
|
||||||
&GUID_DEVICE_INTERFACE_REMOVAL))
|
|
||||||
{
|
|
||||||
DPRINT1("Remove interface to audio device!\n");
|
|
||||||
///FIXME
|
|
||||||
///
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UNICODE_STRING EventName, InterfaceGuid;
|
DPRINT1("Remove interface to audio device!\n");
|
||||||
|
UNIMPLEMENTED
|
||||||
RtlStringFromGUID(&Event->Event, &EventName);
|
|
||||||
RtlStringFromGUID(&Event->InterfaceClassGuid, &InterfaceGuid);
|
|
||||||
DPRINT1("Unknown event: Event %wZ GUID %wZ\n", &EventName, &InterfaceGuid);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -24,17 +24,13 @@ Dispatch_fnDeviceIoControl(
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
//DPRINT("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
||||||
{
|
{
|
||||||
return SysAudioHandleProperty(DeviceObject, Irp);
|
return SysAudioHandleProperty(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Dispatch_fnDeviceIoControl Unhandeled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
/* unsupported request */
|
||||||
DbgBreakPoint();
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -47,8 +43,7 @@ Dispatch_fnRead(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT1("Dispatch_fnRead called DeviceObject %p Irp %p\n", DeviceObject);
|
/* unsupported request */
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -61,8 +56,7 @@ Dispatch_fnWrite(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT1("Dispatch_fnWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
/* unsupported request */
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -75,9 +69,6 @@ Dispatch_fnFlush(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT1("Dispatch_fnFlush called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
//FIXME
|
|
||||||
// cleanup resources
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -127,8 +118,9 @@ Dispatch_fnClose(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* this is pin which can only be instantiated once
|
/* this is a pin which can only be instantiated once
|
||||||
* so we just need to release the reference count on that pin */
|
* so we just need to release the reference count on that pin
|
||||||
|
*/
|
||||||
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
|
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
|
||||||
|
|
||||||
DispatchContext = (PDISPATCH_CONTEXT)Client->Devs[Index].ClientHandles[SubIndex].DispatchContext;
|
DispatchContext = (PDISPATCH_CONTEXT)Client->Devs[Index].ClientHandles[SubIndex].DispatchContext;
|
||||||
|
@ -274,6 +266,8 @@ DispatchCreateSysAudio(
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
PIO_STACK_LOCATION IoStatus;
|
PIO_STACK_LOCATION IoStatus;
|
||||||
LPWSTR Buffer;
|
LPWSTR Buffer;
|
||||||
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||||
|
|
||||||
|
@ -300,16 +294,55 @@ DispatchCreateSysAudio(
|
||||||
/* allocate create item */
|
/* allocate create item */
|
||||||
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
if (!CreateItem)
|
if (!CreateItem)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
Client = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT));
|
Client = ExAllocatePool(NonPagedPool, sizeof(SYSAUDIO_CLIENT));
|
||||||
if (!Client)
|
if (!Client)
|
||||||
{
|
{
|
||||||
ExFreePool(CreateItem);
|
ExFreePool(CreateItem);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
/* initialize client struct */
|
|
||||||
RtlZeroMemory(Client, sizeof(SYSAUDIO_CLIENT));
|
/* 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 */
|
/* zero create struct */
|
||||||
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
|
|
|
@ -46,27 +46,33 @@ SysAudio_Pnp(
|
||||||
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
||||||
SYSAUDIODEVEXT *DeviceExtension;
|
SYSAUDIODEVEXT *DeviceExtension;
|
||||||
|
|
||||||
|
/* Get current irp stack */
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
DPRINT("SysAudio_Pnp called for func %x\n", IrpStack->MinorFunction);
|
/* Fetch the device extension */
|
||||||
|
|
||||||
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(DeviceExtension);
|
||||||
|
|
||||||
if (IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
if (IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
||||||
{
|
{
|
||||||
|
/* Unregister the echo cancel hook */
|
||||||
if (DeviceExtension->EchoCancelNotificationEntry)
|
if (DeviceExtension->EchoCancelNotificationEntry)
|
||||||
IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
|
IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
|
||||||
|
|
||||||
|
/* Unregister the ks audio hook */
|
||||||
if (DeviceExtension->KsAudioNotificationEntry)
|
if (DeviceExtension->KsAudioNotificationEntry)
|
||||||
IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
|
IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
|
||||||
|
|
||||||
|
/* Destroy our symbolic link */
|
||||||
IoDeleteSymbolicLink(&SymlinkName);
|
IoDeleteSymbolicLink(&SymlinkName);
|
||||||
}
|
}
|
||||||
else if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
|
else if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
|
||||||
{
|
{
|
||||||
|
/* Sysaudio can not be disabled */
|
||||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform default pnp actions */
|
||||||
return KsDefaultDispatchPnp(DeviceObject, Irp);
|
return KsDefaultDispatchPnp(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +85,12 @@ SysAudio_InstallDevice(
|
||||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
|
||||||
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
//PDEVICE_OBJECT NextDeviceObject;
|
|
||||||
SYSAUDIODEVEXT *DeviceExtension;
|
SYSAUDIODEVEXT *DeviceExtension;
|
||||||
|
|
||||||
|
|
||||||
DPRINT1("SysAudio_InstallDevice called\n");
|
DPRINT1("SysAudio_InstallDevice called\n");
|
||||||
|
|
||||||
/* create the device */
|
/* Create the device */
|
||||||
Status = IoCreateDevice(DriverObject,
|
Status = IoCreateDevice(DriverObject,
|
||||||
sizeof(SYSAUDIODEVEXT),
|
sizeof(SYSAUDIODEVEXT),
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
|
@ -94,19 +99,19 @@ SysAudio_InstallDevice(
|
||||||
FALSE,
|
FALSE,
|
||||||
&DeviceObject);
|
&DeviceObject);
|
||||||
|
|
||||||
/* check for success */
|
/* Check for success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("Failed to create \\Device\\sysaudio !\n");
|
DPRINT("Failed to create \\Device\\sysaudio !\n");
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register device interfaces */
|
/* Register device interfaces */
|
||||||
Status = SysAudioRegisterDeviceInterfaces(DeviceObject);
|
Status = SysAudioRegisterDeviceInterfaces(DeviceObject);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* failed to register
|
/* Failed to register
|
||||||
* create a hack interface
|
* Create a hack interface
|
||||||
*/
|
*/
|
||||||
Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -116,15 +121,18 @@ SysAudio_InstallDevice(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Acquire device extension */
|
||||||
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
||||||
/* initialize device extension */
|
/* Initialize device extension */
|
||||||
RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
|
RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
|
||||||
|
|
||||||
|
/* Initialize the mutex */
|
||||||
KeInitializeMutex(&DeviceExtension->Mutex, 0);
|
KeInitializeMutex(&DeviceExtension->Mutex, 0);
|
||||||
//DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
|
||||||
|
/* Initialize the ks audio device list */
|
||||||
InitializeListHead(&DeviceExtension->KsAudioDeviceList);
|
InitializeListHead(&DeviceExtension->KsAudioDeviceList);
|
||||||
|
|
||||||
|
/* Allocate kernel streaming device header */
|
||||||
Status = SysAudioAllocateDeviceHeader(DeviceExtension);
|
Status = SysAudioAllocateDeviceHeader(DeviceExtension);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -132,6 +140,7 @@ SysAudio_InstallDevice(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Register device notification hooks */
|
||||||
Status = SysAudioRegisterNotifications(DriverObject,
|
Status = SysAudioRegisterNotifications(DriverObject,
|
||||||
DeviceObject);
|
DeviceObject);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -140,6 +149,7 @@ SysAudio_InstallDevice(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load kmixer */
|
||||||
Status = SysAudioOpenKMixer(DeviceExtension);
|
Status = SysAudioOpenKMixer(DeviceExtension);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -152,7 +162,7 @@ SysAudio_InstallDevice(
|
||||||
/* clear initializing flag */
|
/* clear initializing flag */
|
||||||
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
DPRINT("Device SysAudio_InstallDevice result %x\n", Status);
|
/* Done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -168,22 +178,30 @@ cleanup:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
DriverEntry(
|
DriverEntry(
|
||||||
IN PDRIVER_OBJECT DriverObject,
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
IN PUNICODE_STRING RegistryPath)
|
IN PUNICODE_STRING RegistryPath)
|
||||||
{
|
{
|
||||||
DPRINT1("System audio graph builder (sysaudio) started\n");
|
DPRINT1("System audio graph builder (sysaudio) started\n");
|
||||||
|
|
||||||
|
/* Let ks handle these */
|
||||||
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
|
||||||
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
|
||||||
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
|
||||||
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
|
||||||
|
|
||||||
|
/* Let ks handle these */
|
||||||
DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
|
DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
|
||||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
|
||||||
DriverObject->MajorFunction[IRP_MJ_PNP] = SysAudio_Pnp;
|
|
||||||
DriverObject->DriverUnload = SysAudio_Unload;
|
|
||||||
|
|
||||||
|
/* Use provided ks unload function */
|
||||||
|
DriverObject->DriverUnload = KsNullDriverUnload;
|
||||||
|
|
||||||
|
/* Sysaudio needs to do work on pnp, so handle it */
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = SysAudio_Pnp;
|
||||||
|
|
||||||
|
/* Call our initialization function */
|
||||||
return SysAudio_InstallDevice(DriverObject);
|
return SysAudio_InstallDevice(DriverObject);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,19 @@ Pin_fnDeviceIoControl(
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
/* Get current stack location */
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* The dispatch context is stored in the FsContext2 member */
|
||||||
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
||||||
ASSERT(Context);
|
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
ASSERT(Context);
|
||||||
|
ASSERT(Context->FileObject != NULL);
|
||||||
|
|
||||||
|
/* Re-dispatch the request to the real target pin */
|
||||||
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
|
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
|
||||||
IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
|
IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
|
||||||
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
IoStack->Parameters.DeviceIoControl.InputBufferLength,
|
||||||
|
@ -41,11 +47,12 @@ Pin_fnDeviceIoControl(
|
||||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
|
||||||
&BytesReturned);
|
&BytesReturned);
|
||||||
|
|
||||||
DPRINT1("Status %x\n", Status);
|
/* Save status and information */
|
||||||
|
|
||||||
Irp->IoStatus.Information = BytesReturned;
|
Irp->IoStatus.Information = BytesReturned;
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
/* Complete the irp */
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
/* Done */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,27 +62,43 @@ Pin_fnRead(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT1("Pin_fnRead called DeviceObject %p Irp %p\n", DeviceObject);
|
PDISPATCH_CONTEXT Context;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
/* Get current stack location */
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* The dispatch context is stored in the FsContext2 member */
|
||||||
|
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
ASSERT(Context);
|
||||||
|
ASSERT(Context->FileObject != NULL);
|
||||||
|
|
||||||
|
/* Re-dispatch the request to the real target pin */
|
||||||
|
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_READ_STREAM,
|
||||||
|
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
||||||
|
IoStack->Parameters.Read.Length,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BytesReturned);
|
||||||
|
|
||||||
|
if (Context->hMixerPin && Context->MixerFileObject)
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
// call kmixer to convert stream
|
||||||
|
UNIMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save status and information */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
/* Complete the irp */
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_UNSUCCESSFUL;
|
/* Done */
|
||||||
}
|
return Status;
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
PinWriteCompletionRoutine(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp,
|
|
||||||
IN PVOID Context)
|
|
||||||
{
|
|
||||||
PIRP CIrp = (PIRP)Context;
|
|
||||||
|
|
||||||
CIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
CIrp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(CIrp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -89,23 +112,38 @@ Pin_fnWrite(
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT1("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
/* Get current stack location */
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* The dispatch context is stored in the FsContext2 member */
|
||||||
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
||||||
ASSERT(Context);
|
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
ASSERT(Context);
|
||||||
|
ASSERT(Context->FileObject != NULL);
|
||||||
|
|
||||||
|
if (Context->hMixerPin && Context->MixerFileObject)
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
// call kmixer to convert stream
|
||||||
|
UNIMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Re-dispatch the request to the real target pin */
|
||||||
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
|
||||||
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
MmGetMdlVirtualAddress(Irp->MdlAddress),
|
||||||
IoStack->Parameters.Write.Length,
|
IoStack->Parameters.Read.Length,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
&BytesReturned);
|
&BytesReturned);
|
||||||
|
|
||||||
Irp->IoStatus.Information = BytesReturned;
|
/* Save status and information */
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
/* Complete the irp */
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
/* Done */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,12 +153,59 @@ Pin_fnFlush(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT1("Pin_fnFlush called DeviceObject %p Irp %p\n", DeviceObject);
|
PDISPATCH_CONTEXT Context;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PDEVICE_OBJECT PinDeviceObject;
|
||||||
|
PIRP PinIrp;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
/* Get current stack location */
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* The dispatch context is stored in the FsContext2 member */
|
||||||
|
Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
ASSERT(Context);
|
||||||
|
ASSERT(Context->FileObject != NULL);
|
||||||
|
|
||||||
|
/* Get Pin's device object */
|
||||||
|
PinDeviceObject = IoGetRelatedDeviceObject(Context->FileObject);
|
||||||
|
|
||||||
|
/* Initialize notification event */
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
|
/* build target irp */
|
||||||
|
PinIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, PinDeviceObject, NULL, 0, NULL, &Event, &IoStatus);
|
||||||
|
if (PinIrp)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* call the driver */
|
||||||
|
Status = IoCallDriver(PinDeviceObject, PinIrp);
|
||||||
|
/* Has request already completed ? */
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* Wait untill the request has completed */
|
||||||
|
KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
|
||||||
|
/* Update status */
|
||||||
|
Status = IoStatus.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store status */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
/* Complete the irp */
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_UNSUCCESSFUL;
|
/* Done */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -3,84 +3,93 @@
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
BOOL bHandle;
|
BOOL bHandle; // indicates if an audio pin can be instantated more than once
|
||||||
ULONG PinId;
|
ULONG PinId; // specifies the pin id
|
||||||
HANDLE hPin;
|
HANDLE hPin; // handle to audio irp pin
|
||||||
HANDLE hMixer;
|
HANDLE hMixer; // handle to mixer pin
|
||||||
PVOID DispatchContext;
|
PVOID DispatchContext; // pointer to dispatch context
|
||||||
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
|
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG DeviceId;
|
ULONG DeviceId; //specifies the device id
|
||||||
ULONG ClientHandlesCount;
|
ULONG ClientHandlesCount; // number of client handles
|
||||||
PSYSAUDIO_PIN_HANDLE ClientHandles;
|
PSYSAUDIO_PIN_HANDLE ClientHandles; // array of client handles
|
||||||
|
|
||||||
}SYSAUDIO_CLIENT_HANDELS, *PSYSAUDIO_CLIENT_HANDELS;
|
}SYSAUDIO_CLIENT_HANDELS, *PSYSAUDIO_CLIENT_HANDELS;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG NumDevices;
|
ULONG NumDevices; // number of devices in Devs array
|
||||||
PSYSAUDIO_CLIENT_HANDELS Devs;
|
PSYSAUDIO_CLIENT_HANDELS Devs; // array of client handles
|
||||||
|
|
||||||
}SYSAUDIO_CLIENT, *PSYSAUDIO_CLIENT;
|
}SYSAUDIO_CLIENT, *PSYSAUDIO_CLIENT;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG MaxPinInstanceCount;
|
ULONG MaxPinInstanceCount; // maximum times a audio irp pin can be instantiated
|
||||||
HANDLE PinHandle;
|
HANDLE PinHandle; // handle to audio irp pin
|
||||||
ULONG References;
|
ULONG References; // number of clients having a reference to this audio irp pin
|
||||||
KSPIN_DATAFLOW DataFlow;
|
KSPIN_DATAFLOW DataFlow; // specifies data flow
|
||||||
KSPIN_COMMUNICATION Communication;
|
KSPIN_COMMUNICATION Communication; // pin type
|
||||||
}PIN_INFO;
|
}PIN_INFO;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry; // device entry for KsAudioDeviceList
|
||||||
HANDLE Handle;
|
HANDLE Handle; // handle to audio device
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject; // file object for audio device
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName; // symbolic link of audio device
|
||||||
ULONG NumberOfClients;
|
ULONG NumberOfClients; // number of clients referenced audio device
|
||||||
|
|
||||||
ULONG NumberOfPins;
|
ULONG NumberOfPins; // number of pins of audio device
|
||||||
PIN_INFO * Pins;
|
PIN_INFO * Pins; // array of PIN_INFO
|
||||||
|
|
||||||
ULONG NumWaveOutPin;
|
ULONG NumWaveOutPin; // number of wave out pins
|
||||||
ULONG NumWaveInPin;
|
ULONG NumWaveInPin; // number of wave in pins
|
||||||
|
|
||||||
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
KSDEVICE_HEADER KsDeviceHeader;
|
KSDEVICE_HEADER KsDeviceHeader; // ks streaming header - must always be first item in device extension
|
||||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
PDEVICE_OBJECT PhysicalDeviceObject; // pdo
|
||||||
PDEVICE_OBJECT NextDeviceObject;
|
PDEVICE_OBJECT NextDeviceObject; // lower device object
|
||||||
ULONG NumberOfKsAudioDevices;
|
ULONG NumberOfKsAudioDevices; // number of audio devices
|
||||||
|
|
||||||
LIST_ENTRY KsAudioDeviceList;
|
LIST_ENTRY KsAudioDeviceList; // audio device list
|
||||||
PVOID KsAudioNotificationEntry;
|
PVOID KsAudioNotificationEntry; // ks audio notification hook
|
||||||
PVOID EchoCancelNotificationEntry;
|
PVOID EchoCancelNotificationEntry; // ks echo cancel notification hook
|
||||||
KMUTEX Mutex;
|
KMUTEX Mutex; // audio device list mutex
|
||||||
|
|
||||||
PFILE_OBJECT KMixerFileObject;
|
PFILE_OBJECT KMixerFileObject; // mixer file object
|
||||||
HANDLE KMixerHandle;
|
HANDLE KMixerHandle; // mixer file handle
|
||||||
|
|
||||||
}SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
|
}SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
|
||||||
|
|
||||||
|
// struct DISPATCH_CONTEXT
|
||||||
|
//
|
||||||
|
// This structure is used to dispatch read / write / device io requests
|
||||||
|
// It is stored in the file object FsContext2 member
|
||||||
|
// Note: FsContext member is reserved for ks object header
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
HANDLE Handle; // audio irp pin handle
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject; // audio irp pin file object
|
||||||
ULONG PinId;
|
ULONG PinId; // pin id of device
|
||||||
PKSAUDIO_DEVICE_ENTRY AudioEntry;
|
PKSAUDIO_DEVICE_ENTRY AudioEntry; // pointer to audio device entry
|
||||||
|
|
||||||
HANDLE hMixerPin;
|
HANDLE hMixerPin; // handle to mixer pin
|
||||||
PFILE_OBJECT MixerFileObject;
|
PFILE_OBJECT MixerFileObject; // mixer file object
|
||||||
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
||||||
|
|
||||||
|
// struct PIN_WORKER_CONTEXT
|
||||||
|
//
|
||||||
|
// This structure holds all information required
|
||||||
|
// to create audio irp pin, mixer pin and virtual sysaudio pin
|
||||||
|
//
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue