mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
558 lines
18 KiB
558 lines
18 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1996
|
|
|
|
Module Name:
|
|
|
|
msmpu401.c
|
|
|
|
Abstract:
|
|
|
|
Pin property sets.
|
|
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PropertyConnectionGetState)
|
|
#pragma alloc_text(PAGE, PropertyConnectionGetPriority)
|
|
#pragma alloc_text(PAGE, PropertyConnectionSetPriority)
|
|
#pragma alloc_text(PAGE, PropertyConnectionGetDataFormat)
|
|
#pragma alloc_text(PAGE, MethodConnectionCancelIo)
|
|
#pragma alloc_text(PAGE, PinDispatchClose)
|
|
#pragma alloc_text(PAGE, PinDispatchCreate)
|
|
#pragma alloc_text(PAGE, PinDispatchIoControl)
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg("PAGEDATA")
|
|
#endif // ALLOC_DATA_PRAGMA
|
|
|
|
static const KSDISPATCH_TABLE PinDispatchTable = {
|
|
0,
|
|
NULL,
|
|
PinDispatchIoControl,
|
|
NULL,
|
|
NULL,
|
|
PinDispatchClose
|
|
};
|
|
|
|
static const KSPROPERTY_ITEM ConnectionPropertyHandlers[] = {
|
|
{
|
|
KSPROPERTY_CONNECTION_STATE,
|
|
(PFNKSPROPERTYHANDLER)PropertyConnectionGetState,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(KSSTATE),
|
|
(PFNKSPROPERTYHANDLER)PropertyConnectionSetState,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(KSSTATE),
|
|
NULL, 0, NULL, NULL
|
|
},
|
|
{
|
|
KSPROPERTY_CONNECTION_PRIORITY,
|
|
(PFNKSPROPERTYHANDLER)PropertyConnectionGetPriority,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(KSPRIORITY),
|
|
(PFNKSPROPERTYHANDLER)PropertyConnectionSetPriority,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(KSPRIORITY),
|
|
NULL, 0, NULL, NULL
|
|
},
|
|
{
|
|
KSPROPERTY_CONNECTION_DATAFORMAT,
|
|
(PFNKSPROPERTYHANDLER)PropertyConnectionGetDataFormat,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(KSDATAFORMAT),
|
|
NULL, 0, 0, NULL, 0, NULL, NULL
|
|
}
|
|
};
|
|
|
|
static const KSPROPERTY_ITEM LinearPropertyHandlers[] = {
|
|
{
|
|
KSPROPERTY_LINEAR_POSITION,
|
|
(PFNKSPROPERTYHANDLER)PropertyLinearGetPosition,
|
|
sizeof(KSPROPERTY),
|
|
sizeof(ULONGLONG),
|
|
NULL, 0, 0, NULL, 0, NULL, NULL
|
|
}
|
|
};
|
|
|
|
static const KSPROPERTY_SET PinPropertySets[] = {
|
|
{
|
|
&KSPROPSETID_Connection,
|
|
SIZEOF_ARRAY(ConnectionPropertyHandlers),
|
|
(PKSPROPERTY_ITEM)ConnectionPropertyHandlers,
|
|
0, NULL, 0, 0
|
|
},
|
|
{
|
|
&KSPROPSETID_Linear,
|
|
SIZEOF_ARRAY(LinearPropertyHandlers),
|
|
(PKSPROPERTY_ITEM)LinearPropertyHandlers,
|
|
0, NULL, 0, 0
|
|
}
|
|
};
|
|
|
|
static const KSEVENT_ITEM ConnectionEventItems[] = {
|
|
{
|
|
KSEVENT_CONNECTION_POSITIONUPDATE,
|
|
sizeof(KSEVENTDATA),
|
|
0, NULL, NULL, NULL
|
|
}
|
|
};
|
|
|
|
static const KSEVENT_SET EventSets[] = {
|
|
{
|
|
&KSEVENTSETID_Connection,
|
|
SIZEOF_ARRAY(ConnectionEventItems),
|
|
(PKSEVENT_ITEM)ConnectionEventItems
|
|
}
|
|
};
|
|
|
|
static const KSMETHOD_ITEM ConnectionMethodItems[] = {
|
|
{
|
|
KSMETHOD_CONNECTION_CANCELIO + KSMETHOD_TYPE_NONE,
|
|
MethodConnectionCancelIo,
|
|
sizeof(KSMETHOD),
|
|
0, NULL
|
|
},
|
|
};
|
|
|
|
static const KSMETHOD_SET MethodSets[] = {
|
|
{
|
|
&KSMETHODSETID_Connection,
|
|
SIZEOF_ARRAY(ConnectionMethodItems),
|
|
(PVOID)ConnectionMethodItems,
|
|
0, NULL, 0, 0
|
|
},
|
|
};
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg()
|
|
#endif // ALLOC_DATA_PRAGMA
|
|
|
|
VOID
|
|
PinGenerateEvent(
|
|
IN PPIN_INSTANCE PinInstance,
|
|
IN REFGUID EventSet,
|
|
IN ULONG EventId
|
|
)
|
|
{
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
for (ListEntry = PinInstance->EventQueue.Flink; ListEntry != &PinInstance->EventQueue; ListEntry = ListEntry->Flink) {
|
|
PKSEVENT_ENTRY EventEntry;
|
|
|
|
EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(ListEntry, KSEVENT_ENTRY, ListEntry);
|
|
if (IsEqualGUIDAligned(EventSet, EventEntry->EventSet->Set))
|
|
if (EventId == EventEntry->EventItem->EventId)
|
|
switch (EventId) {
|
|
case KSEVENT_CONNECTION_POSITIONUPDATE:
|
|
KsEventGenerate(EventEntry);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static
|
|
BOOLEAN
|
|
DpcCountSynchronize(
|
|
IN PDEVICE_INSTANCE DeviceInstance
|
|
)
|
|
{
|
|
return !DeviceInstance->DpcCount;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
RundownProcessing(
|
|
IN PDEVICE_INSTANCE DeviceInstance,
|
|
IN PPIN_INSTANCE PinInstance
|
|
)
|
|
{
|
|
switch (PinInstance->PinId) {
|
|
case ID_MUSICCAPTURE_PIN:
|
|
while (!KeSynchronizeExecution(DeviceInstance->InterruptInfo.Interrupt, DpcCountSynchronize, DeviceInstance))
|
|
KeStallExecutionProcessor(1);
|
|
break;
|
|
case ID_MUSICPLAYBACK_PIN:
|
|
if (KeCancelTimer(&PinInstance->QueueTimer))
|
|
InterlockedDecrement(&PinInstance->TimerCount);
|
|
while (PinInstance->TimerCount)
|
|
KeStallExecutionProcessor(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
SetState(
|
|
IN PPIN_INSTANCE PinInstance,
|
|
IN KSSTATE State
|
|
)
|
|
{
|
|
ULONGLONG Time;
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
|
|
if (PinInstance->State == State)
|
|
return STATUS_SUCCESS;
|
|
DeviceInstance = (PDEVICE_INSTANCE)IoGetRelatedDeviceObject(PinInstance->FilterFileObject)->DeviceExtension;
|
|
switch (State) {
|
|
case KSSTATE_STOP:
|
|
InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_STOP);
|
|
RundownProcessing(DeviceInstance, PinInstance);
|
|
PinInstance->TimeBase = 0;
|
|
PinInstance->ByteIo = 0;
|
|
break;
|
|
case KSSTATE_PAUSE:
|
|
if (PinInstance->State == KSSTATE_RUN) {
|
|
InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_PAUSE);
|
|
RundownProcessing(DeviceInstance, PinInstance);
|
|
PinInstance->TimeBase = KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase;
|
|
} else
|
|
InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_PAUSE);
|
|
break;
|
|
case KSSTATE_RUN:
|
|
Time = KeQueryPerformanceCounter(NULL).QuadPart;
|
|
if (PinInstance->State == KSSTATE_STOP)
|
|
PinInstance->TimeBase = Time;
|
|
else
|
|
PinInstance->TimeBase = Time - PinInstance->TimeBase;
|
|
InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_RUN);
|
|
Time = 0;
|
|
if (!PinInstance->QueueTimer.Header.Inserted && !KeSetTimerEx(&PinInstance->QueueTimer, *(PLARGE_INTEGER)&Time, 0, &PinInstance->QueueDpc))
|
|
InterlockedIncrement(&PinInstance->TimerCount);
|
|
break;
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyConnectionGetState(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
OUT PKSSTATE State
|
|
)
|
|
{
|
|
*State = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->State;
|
|
Irp->IoStatus.Information = sizeof(KSSTATE);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyConnectionSetState(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
IN PKSSTATE State
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PPIN_INSTANCE PinInstance;
|
|
KIRQL IrqlOld;
|
|
|
|
PinInstance = (PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext;
|
|
KeAcquireSpinLock(&PinInstance->StateLock, &IrqlOld);
|
|
Status = SetState(PinInstance, *State);
|
|
KeReleaseSpinLock(&PinInstance->StateLock, IrqlOld);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyConnectionGetPriority(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
OUT PKSPRIORITY Priority
|
|
)
|
|
{
|
|
*Priority = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->Priority;
|
|
Irp->IoStatus.Information = sizeof(KSPRIORITY);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyConnectionSetPriority(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
IN PKSPRIORITY Priority
|
|
)
|
|
{
|
|
((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->Priority = *Priority;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyConnectionGetDataFormat(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
OUT PKSDATAFORMAT DataFormat
|
|
)
|
|
{
|
|
DataFormat->MajorFormat = KSDATAFORMAT_TYPE_MUSIC;
|
|
DataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_MIDI;
|
|
DataFormat->Specifier = KSDATAFORMAT_FORMAT_NONE;
|
|
DataFormat->FormatSize = sizeof(KSDATAFORMAT);
|
|
Irp->IoStatus.Information = sizeof(KSDATAFORMAT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PropertyLinearGetPosition(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
OUT PULONGLONG Position
|
|
)
|
|
{
|
|
KIRQL IrqlOld;
|
|
|
|
IoAcquireCancelSpinLock(&IrqlOld);
|
|
*Position = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->ByteIo;
|
|
IoReleaseCancelSpinLock(IrqlOld);
|
|
Irp->IoStatus.Information = sizeof(ULONGLONG);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#if 0
|
|
NTSTATUS
|
|
propTimeBase(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY Property,
|
|
IN OUT PVOID Data
|
|
)
|
|
{
|
|
PPIN_INSTANCE PinInstance;
|
|
KIRQL IrqlOld;
|
|
|
|
PinInstance = (PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext;
|
|
KeAcquireSpinLock(&PinInstance->StateLock, &IrqlOld);
|
|
switch (PinInstance->State) {
|
|
case KSSTATE_STOP:
|
|
case KSSTATE_PAUSE:
|
|
*(PULONGLONG)Data = KeQueryPerformanceCounter(NULL).QuadPart - pci->TimeBase;
|
|
break;
|
|
case KSSTATE_RUN:
|
|
*(PULONGLONG)Data = pci->TimeBase;
|
|
break;
|
|
}
|
|
KeReleaseSpinLock(&PinInstance->StateLock, IrqlOld);
|
|
Irp->IoStatus.Information = sizeof(ULONGLONG);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif // 0
|
|
|
|
NTSTATUS
|
|
MethodConnectionCancelIo(
|
|
IN PIRP Irp,
|
|
IN PKSMETHOD Method,
|
|
IN OUT PVOID Data
|
|
)
|
|
{
|
|
KsCancelIo(&((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->IoQueue);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS PinDispatchClose(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
|
|
SetState(PinInstance, KSSTATE_STOP);
|
|
KsEventFreeList(Irp, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
|
|
DeviceInstance = (PDEVICE_INSTANCE)IrpStack->DeviceObject->DeviceExtension;
|
|
DeviceInstance->PinFileObjects[PinInstance->PinId] = NULL;
|
|
ObDereferenceObject(PinInstance->FilterFileObject);
|
|
ExFreePool(PinInstance);
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PinDispatchCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
PKSPIN_CONNECT Connect;
|
|
PFILE_OBJECT FilterFileObject;
|
|
NTSTATUS Status;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
if (NT_SUCCESS(Status = KsValidateConnectRequest(Irp, SIZEOF_ARRAY(FilterPinDescriptors), (PKSPIN_DESCRIPTOR)FilterPinDescriptors, &Connect, &FilterFileObject))) {
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
|
|
DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
|
|
ExAcquireFastMutexUnsafe(&DeviceInstance->ControlMutex);
|
|
if (!DeviceInstance->PinFileObjects[Connect->PinId]) {
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
if (PinInstance = (PPIN_INSTANCE)ExAllocatePool(NonPagedPool, sizeof(PIN_INSTANCE))) {
|
|
IrpStack->FileObject->FsContext = (PVOID)PinInstance;
|
|
PinInstance->DispatchTable = (PKSDISPATCH_TABLE)&PinDispatchTable;
|
|
KeQueryPerformanceCounter((PLARGE_INTEGER)&PinInstance->Frequency);
|
|
PinInstance->State = KSSTATE_STOP;
|
|
PinInstance->PinId = Connect->PinId;
|
|
InitializeListHead(&PinInstance->IoQueue);
|
|
InitializeListHead(&PinInstance->EventQueue);
|
|
KeInitializeSpinLock(&PinInstance->EventQueueLock);
|
|
PinInstance->TimeBase = 0;
|
|
PinInstance->ByteIo = 0;
|
|
KeInitializeSpinLock(&PinInstance->StateLock);
|
|
if (Connect->PinId == ID_MUSICPLAYBACK_PIN) {
|
|
KeInitializeTimerEx(&PinInstance->QueueTimer, NotificationTimer);
|
|
KeInitializeDpc(&PinInstance->QueueDpc, (PKDEFERRED_ROUTINE)HwDeferredWrite, DeviceObject);
|
|
PinInstance->TimerCount = 0;
|
|
}
|
|
PinInstance->FilterFileObject = FilterFileObject;
|
|
ObReferenceObject(FilterFileObject);
|
|
PinInstance->Priority = Connect->Priority;
|
|
DeviceInstance->PinFileObjects[Connect->PinId] = IrpStack->FileObject;
|
|
} else
|
|
Status = STATUS_NO_MEMORY;
|
|
} else
|
|
Status = STATUS_CONNECTION_REFUSED;
|
|
ExReleaseFastMutexUnsafe(&DeviceInstance->ControlMutex);
|
|
}
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
WriteStream(
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
NTSTATUS Status;
|
|
PULONG UserBuffer;
|
|
KIRQL IrqlOld;
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
Irp->IoStatus.Information = 0;
|
|
if (!IrpStack->Parameters.DeviceIoControl.InputBufferLength)
|
|
return STATUS_SUCCESS;
|
|
if (!NT_SUCCESS(Status = KsProbeStreamIrp(Irp, KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK)))
|
|
return Status;
|
|
UserBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
if ((ULONG)UserBuffer & FILE_LONG_ALIGNMENT)
|
|
return STATUS_DATATYPE_MISALIGNMENT;
|
|
if (((PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer)->DataSize < 2 * sizeof(ULONG) + sizeof(UCHAR))
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
Irp->Tail.Overlay.AuxiliaryBuffer = (PUCHAR)UserBuffer;
|
|
Irp->IoStatus.Information = 2 * sizeof(ULONG);
|
|
IoMarkIrpPending(Irp);
|
|
Irp->IoStatus.Status = STATUS_PENDING;
|
|
IoAcquireCancelSpinLock(&IrqlOld);
|
|
IoSetCancelRoutine(Irp, HwCancelRoutine);
|
|
PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
|
|
InsertTailList(&PinInstance->IoQueue, &Irp->Tail.Overlay.ListEntry);
|
|
KeAcquireSpinLockAtDpcLevel(&PinInstance->StateLock);
|
|
if ((PinInstance->State == KSSTATE_RUN) && !PinInstance->QueueTimer.Header.Inserted) {
|
|
ULONGLONG CurrentTime;
|
|
ULONGLONG NextTime;
|
|
|
|
CurrentTime = (KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 10000000 / PinInstance->Frequency;
|
|
NextTime = ((PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer)->PresentationTime.Time + *UserBuffer * 10000;
|
|
if (NextTime < CurrentTime)
|
|
NextTime = 0;
|
|
else
|
|
NextTime = (ULONGLONG)-(LONGLONG)(NextTime - CurrentTime);
|
|
if (!KeSetTimerEx(&PinInstance->QueueTimer, *(PLARGE_INTEGER)&NextTime, 0, &PinInstance->QueueDpc))
|
|
InterlockedIncrement(&PinInstance->TimerCount);
|
|
}
|
|
KeReleaseSpinLockFromDpcLevel(&PinInstance->StateLock);
|
|
IoReleaseCancelSpinLock(IrqlOld);
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
ReadStream(
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
NTSTATUS Status;
|
|
PULONG UserBuffer;
|
|
PKSSTREAM_HEADER StreamHdr;
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < 2 * sizeof(ULONG) + sizeof(UCHAR))
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
if (!NT_SUCCESS(Status = KsProbeStreamIrp(Irp, KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK)))
|
|
return Status;
|
|
UserBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
if ((ULONG)UserBuffer & FILE_LONG_ALIGNMENT)
|
|
return STATUS_DATATYPE_MISALIGNMENT;
|
|
MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
Irp->IoStatus.Information = sizeof(KSSTREAM_HEADER);
|
|
StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
|
|
StreamHdr->PresentationTime.Time = 0;
|
|
StreamHdr->PresentationTime.Numerator = 1;
|
|
StreamHdr->PresentationTime.Denominator = 1;
|
|
StreamHdr->DataSize = 0;
|
|
StreamHdr->OptionsFlags = 0;
|
|
PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
|
|
KsAddIrpToCancelableQueue(&PinInstance->IoQueue, Irp, FALSE, HwCancelRoutine);
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
NTSTATUS
|
|
PinDispatchIoControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpStack;
|
|
NTSTATUS Status;
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
|
|
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
|
|
case IOCTL_KS_GET_PROPERTY:
|
|
case IOCTL_KS_SET_PROPERTY:
|
|
Status = KsPropertyHandler(Irp, SIZEOF_ARRAY(PinPropertySets), (PKSPROPERTY_SET)PinPropertySets);
|
|
break;
|
|
case IOCTL_KS_ENABLE_EVENT:
|
|
Status = KsEventEnable(Irp, SIZEOF_ARRAY(EventSets), (PKSEVENT_SET)EventSets, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
|
|
break;
|
|
case IOCTL_KS_DISABLE_EVENT:
|
|
Status = KsEventDisable(Irp, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
|
|
break;
|
|
case IOCTL_KS_METHOD:
|
|
Status = KsMethodHandler(Irp, SIZEOF_ARRAY(MethodSets), (PKSMETHOD_SET)MethodSets);
|
|
break;
|
|
case IOCTL_KS_READ_STREAM:
|
|
if (PinInstance->PinId == ID_MUSICCAPTURE_PIN)
|
|
Status = ReadStream(Irp);
|
|
else
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
case IOCTL_KS_WRITE_STREAM:
|
|
if (PinInstance->PinId == ID_MUSICPLAYBACK_PIN)
|
|
Status = WriteStream(Irp);
|
|
else
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
default:
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
if (Status != STATUS_PENDING) {
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
return Status;
|
|
}
|