reactos/drivers/ksfilter/ks/clocks.c
2021-06-11 15:33:08 +03:00

577 lines
13 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/ksfilter/ks/clocks.c
* PURPOSE: KS Clocks functions
* PROGRAMMER: Johannes Anderwald
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
typedef struct
{
LONGLONG Time;
KSPIN_LOCK TimeLock;
KSSTATE State;
KTIMER Timer;
LONG ReferenceCount;
PVOID Context;
PFNKSSETTIMER SetTimer;
PFNKSCANCELTIMER CancelTimer;
PFNKSCORRELATEDTIME CorrelatedTime;
LONGLONG Granularity;
LONGLONG Error;
ULONG Flags;
}KSIDEFAULTCLOCK, *PKSIDEFAULTCLOCK;
typedef struct
{
LONG ref;
PKSCLOCK_CREATE ClockCreate;
PKSIDEFAULTCLOCK DefaultClock;
PKSIOBJECT_HEADER ObjectHeader;
}KSICLOCK, *PKSICLOCK;
NTSTATUS NTAPI ClockPropertyTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyPhysicalTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyCorrelatedTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyCorrelatedPhysicalTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyResolution(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI ClockPropertyFunctionTable(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
DEFINE_KSPROPERTY_CLOCKSET(ClockPropertyTable, ClockPropertyTime, ClockPropertyPhysicalTime, ClockPropertyCorrelatedTime, ClockPropertyCorrelatedPhysicalTime, ClockPropertyResolution, ClockPropertyState, ClockPropertyFunctionTable);
KSPROPERTY_SET ClockPropertySet[] =
{
{
&KSPROPSETID_Clock,
sizeof(ClockPropertyTable) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&ClockPropertyTable,
0,
NULL
}
};
LONGLONG
FASTCALL
ClockGetPhysicalTime(
IN PFILE_OBJECT FileObject)
{
UNIMPLEMENTED;
return 0;
}
LONGLONG
FASTCALL
ClockGetCorrelatedTime(
IN PFILE_OBJECT FileObject,
OUT PLONGLONG SystemTime)
{
UNIMPLEMENTED;
return 0;
}
LONGLONG
FASTCALL
ClockGetTime(
IN PFILE_OBJECT FileObject)
{
UNIMPLEMENTED;
return 0;
}
LONGLONG
FASTCALL
ClockGetCorrelatedPhysicalTime(
IN PFILE_OBJECT FileObject,
OUT PLONGLONG SystemTime)
{
UNIMPLEMENTED;
return 0;
}
NTSTATUS
NTAPI
ClockPropertyTime(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PLONGLONG Time = (PLONGLONG)Data;
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("ClockPropertyTime\n");
*Time = ClockGetTime(IoStack->FileObject);
Irp->IoStatus.Information = sizeof(LONGLONG);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyPhysicalTime(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PLONGLONG Time = (PLONGLONG)Data;
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("ClockPropertyPhysicalTime\n");
*Time = ClockGetPhysicalTime(IoStack->FileObject);
Irp->IoStatus.Information = sizeof(LONGLONG);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyCorrelatedTime(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PKSCORRELATED_TIME Time = (PKSCORRELATED_TIME)Data;
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("ClockPropertyCorrelatedTime\n");
Time->Time = ClockGetCorrelatedTime(IoStack->FileObject, &Time->SystemTime);
Irp->IoStatus.Information = sizeof(KSCORRELATED_TIME);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyCorrelatedPhysicalTime(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PKSCORRELATED_TIME Time = (PKSCORRELATED_TIME)Data;
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT("ClockPropertyCorrelatedPhysicalTime\n");
Time->Time = ClockGetCorrelatedPhysicalTime(IoStack->FileObject, &Time->SystemTime);
Irp->IoStatus.Information = sizeof(KSCORRELATED_TIME);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyResolution(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PKSICLOCK Clock;
PKSIOBJECT_HEADER ObjectHeader;
PIO_STACK_LOCATION IoStack;
PKSRESOLUTION Resolution = (PKSRESOLUTION)Data;
DPRINT("ClockPropertyResolution\n");
/* get stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get the object header */
ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
/* sanity check */
ASSERT(ObjectHeader);
/* locate ks pin implementation from KSPIN offset */
Clock = (PKSICLOCK)ObjectHeader->ObjectType;
Resolution->Error = Clock->DefaultClock->Error;
Resolution->Granularity = Clock->DefaultClock->Granularity;
Irp->IoStatus.Information = sizeof(KSRESOLUTION);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyState(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PKSICLOCK Clock;
PKSIOBJECT_HEADER ObjectHeader;
PKSSTATE State = (PKSSTATE)Data;
PIO_STACK_LOCATION IoStack;
DPRINT("ClockPropertyState\n");
/* get stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get the object header */
ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
/* sanity check */
ASSERT(ObjectHeader);
/* locate ks pin implementation from KSPIN offset */
Clock = (PKSICLOCK)ObjectHeader->ObjectType;
*State = Clock->DefaultClock->State;
Irp->IoStatus.Information = sizeof(KSSTATE);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ClockPropertyFunctionTable(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PKSCLOCK_FUNCTIONTABLE Table = (PKSCLOCK_FUNCTIONTABLE)Data;
DPRINT("ClockPropertyFunctionTable\n");
Table->GetCorrelatedPhysicalTime = ClockGetCorrelatedPhysicalTime;
Table->GetCorrelatedTime = ClockGetCorrelatedTime;
Table->GetPhysicalTime = ClockGetPhysicalTime;
Table->GetTime = ClockGetTime;
return STATUS_SUCCESS;
}
/*
@implemented
*/
KSDDKAPI NTSTATUS NTAPI
KsCreateClock(
IN HANDLE ConnectionHandle,
IN PKSCLOCK_CREATE ClockCreate,
OUT PHANDLE ClockHandle)
{
return KspCreateObjectType(ConnectionHandle,
KSSTRING_Clock,
ClockCreate,
sizeof(KSCLOCK_CREATE),
GENERIC_READ,
ClockHandle);
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsValidateClockCreateRequest(
IN PIRP Irp,
OUT PKSCLOCK_CREATE* OutClockCreate)
{
PKSCLOCK_CREATE ClockCreate;
NTSTATUS Status;
ULONG Size;
/* minimum request size */
Size = sizeof(KSCLOCK_CREATE);
/* copy create request */
Status = KspCopyCreateRequest(Irp,
KSSTRING_Clock,
&Size,
(PVOID*)&ClockCreate);
if (!NT_SUCCESS(Status))
return Status;
if (ClockCreate->CreateFlags != 0)
{
/* flags must be zero */
FreeItem(ClockCreate);
return STATUS_INVALID_PARAMETER;
}
*OutClockCreate = ClockCreate;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IKsClock_DispatchDeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
UNICODE_STRING GuidString;
PKSPROPERTY Property;
NTSTATUS Status;
DPRINT("IKsClock_DispatchDeviceIoControl\n");
/* get current io stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* FIXME support events */
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
/* sanity check */
ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSPROPERTY));
/* call property handler */
Status = KsPropertyHandler(Irp, 1, ClockPropertySet);
/* get property from input buffer */
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
RtlStringFromGUID(&Property->Set, &GuidString);
DPRINT("IKsClock_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
RtlFreeUnicodeString(&GuidString);
Irp->IoStatus.Status = STATUS_SUCCESS;
CompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
IKsClock_DispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_SUCCESS;
CompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static KSDISPATCH_TABLE DispatchTable =
{
IKsClock_DispatchDeviceIoControl,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
IKsClock_DispatchClose,
KsDispatchQuerySecurity,
KsDispatchSetSecurity,
KsDispatchFastIoDeviceControlFailure,
KsDispatchFastReadFailure,
KsDispatchFastReadFailure,
};
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsCreateDefaultClock(
IN PIRP Irp,
IN PKSDEFAULTCLOCK DefaultClock)
{
NTSTATUS Status;
PKSCLOCK_CREATE ClockCreate;
PKSICLOCK Clock;
Status = KsValidateClockCreateRequest(Irp, &ClockCreate);
if (!NT_SUCCESS(Status))
return Status;
/* let's allocate the clock struct */
Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
if (!Clock)
{
FreeItem(ClockCreate);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* now allocate the object header */
Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
/* did it work */
if (!NT_SUCCESS(Status))
{
/* failed */
FreeItem(ClockCreate);
FreeItem(Clock);
return Status;
}
/* initialize clock */
/* FIXME IKsClock */
Clock->ObjectHeader->ObjectType = (PVOID)Clock;
Clock->ref = 1;
Clock->ClockCreate = ClockCreate;
Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
/* increment reference count */
InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
return Status;
}
/*
@implemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAllocateDefaultClock(
OUT PKSDEFAULTCLOCK* DefaultClock)
{
return KsAllocateDefaultClockEx(DefaultClock, NULL, NULL, NULL, NULL, NULL, 0);
}
/*
@unimplemented
*/
KSDDKAPI
NTSTATUS
NTAPI
KsAllocateDefaultClockEx(
OUT PKSDEFAULTCLOCK* DefaultClock,
IN PVOID Context OPTIONAL,
IN PFNKSSETTIMER SetTimer OPTIONAL,
IN PFNKSCANCELTIMER CancelTimer OPTIONAL,
IN PFNKSCORRELATEDTIME CorrelatedTime OPTIONAL,
IN const KSRESOLUTION* Resolution OPTIONAL,
IN ULONG Flags)
{
PKSIDEFAULTCLOCK Clock;
if (!DefaultClock)
return STATUS_INVALID_PARAMETER_1;
/* allocate default clock */
Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
if (!Clock)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize default clock */
KeInitializeSpinLock(&Clock->TimeLock);
KeInitializeTimer(&Clock->Timer);
Clock->ReferenceCount = 1;
Clock->Context = Context;
Clock->SetTimer = SetTimer;
Clock->CancelTimer = CancelTimer;
Clock->CorrelatedTime = CorrelatedTime;
Clock->Flags = Flags;
if (Resolution)
{
if (SetTimer)
{
Clock->Error = Resolution->Error;
}
if (CorrelatedTime)
{
Clock->Granularity = Resolution->Granularity;
}
}
*DefaultClock = (PKSDEFAULTCLOCK)Clock;
return STATUS_SUCCESS;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsFreeDefaultClock(
IN PKSDEFAULTCLOCK DefaultClock)
{
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
InterlockedDecrement(&Clock->ReferenceCount);
if (Clock->ReferenceCount == 0)
{
/* free default clock */
FreeItem(Clock);
}
}
/*
@implemented
*/
KSDDKAPI
KSSTATE
NTAPI
KsGetDefaultClockState(
IN PKSDEFAULTCLOCK DefaultClock)
{
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
return Clock->State;
}
/*
@unimplemented
*/
KSDDKAPI
VOID
NTAPI
KsSetDefaultClockState(
IN PKSDEFAULTCLOCK DefaultClock,
IN KSSTATE State)
{
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
if (State != Clock->State)
{
/* FIXME set time etc */
Clock->State = State;
}
}
/*
@implemented
*/
KSDDKAPI
LONGLONG
NTAPI
KsGetDefaultClockTime(
IN PKSDEFAULTCLOCK DefaultClock)
{
LONGLONG Time = 0LL;
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
return Time;
}
/*
@implemented
*/
KSDDKAPI
VOID
NTAPI
KsSetDefaultClockTime(
IN PKSDEFAULTCLOCK DefaultClock,
IN LONGLONG Time)
{
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
/* set the time safely */
ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
}