- 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:
Johannes Anderwald 2009-03-25 19:14:04 +00:00
parent bf2b5adf8e
commit 5a37c1fdad
9 changed files with 310 additions and 240 deletions

View file

@ -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)

View file

@ -165,7 +165,7 @@ KsLoadResource(
/* /*
@unimplemented @unimplemented
*/ */
VOID KSDDKAPI VOID NTAPI
KsNullDriverUnload( KsNullDriverUnload(
IN PDRIVER_OBJECT DriverObject) IN PDRIVER_OBJECT DriverObject)
{ {

View file

@ -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;
} }

View file

@ -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)
{ {

View file

@ -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

View file

@ -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));

View file

@ -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);
} }

View file

@ -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

View file

@ -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;