-/* ===============================================================
- Clock Functions
-*/
+/*
+ * 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 "priv.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;
-#include <ntddk.h>
-#include <debug.h>
-#include <ks.h>
+}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 implemention 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 implemention 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;
+}
-}KS_DEFAULT_CLOCK;
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI NTSTATUS NTAPI
KsCreateClock(
IN PKSCLOCK_CREATE ClockCreate,
OUT PHANDLE ClockHandle)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ return KspCreateObjectType(ConnectionHandle,
+ KSSTRING_Clock,
+ ClockCreate,
+ sizeof(KSCLOCK_CREATE),
+ GENERIC_READ,
+ ClockHandle);
}
/*
- @unimplemented
+ @implemented
*/
-KSDDKAPI NTSTATUS NTAPI
+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;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+IKsClock_DispatchClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(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;
-// ExAllocatePoolWithTag(NonPagedPool, sizeof(KS_DEFAULT_CLOCK), 0);
+ /* let's allocate the clock struct */
+ Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
+ if (!Clock)
+ 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(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_UNSUCCESSFUL;
+ return Status;
}
/*
@implemented
*/
-KSDDKAPI NTSTATUS NTAPI
+KSDDKAPI
+NTSTATUS
+NTAPI
KsAllocateDefaultClock(
OUT PKSDEFAULTCLOCK* DefaultClock)
{
/*
@unimplemented
*/
-KSDDKAPI NTSTATUS NTAPI
+KSDDKAPI
+NTSTATUS
+NTAPI
KsAllocateDefaultClockEx(
OUT PKSDEFAULTCLOCK* DefaultClock,
IN PVOID Context OPTIONAL,
IN const KSRESOLUTION* Resolution OPTIONAL,
IN ULONG Flags)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ 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;
}
/*
- @unimplemented
+ @implemented
*/
-KSDDKAPI VOID NTAPI
+KSDDKAPI
+VOID
+NTAPI
KsFreeDefaultClock(
IN PKSDEFAULTCLOCK DefaultClock)
{
- UNIMPLEMENTED;
-}
+ PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
-/*
- @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsValidateClockCreateRequest(
- IN PIRP Irp,
- OUT PKSCLOCK_CREATE* ClockCreate)
-{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ InterlockedDecrement(&Clock->ReferenceCount);
+
+ if (Clock->ReferenceCount == 0)
+ {
+ /* free default clock */
+ FreeItem(Clock);
+ }
}
/*
- @unimplemented
+ @implemented
*/
-KSDDKAPI KSSTATE NTAPI
+KSDDKAPI
+KSSTATE
+NTAPI
KsGetDefaultClockState(
IN PKSDEFAULTCLOCK DefaultClock)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
+ return Clock->State;
}
/*
@unimplemented
*/
-KSDDKAPI VOID NTAPI
+KSDDKAPI
+VOID
+NTAPI
KsSetDefaultClockState(
IN PKSDEFAULTCLOCK DefaultClock,
IN KSSTATE State)
{
- UNIMPLEMENTED;
+ PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
+
+ if (State != Clock->State)
+ {
+ /* FIXME set time etc */
+ Clock->State = State;
+ }
+
}
/*
- @unimplemented
+ @implemented
*/
-KSDDKAPI LONGLONG NTAPI
+KSDDKAPI
+LONGLONG
+NTAPI
KsGetDefaultClockTime(
IN PKSDEFAULTCLOCK DefaultClock)
{
- UNIMPLEMENTED;
- return 0;
+ LONGLONG Time = 0LL;
+ PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
+
+ Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
+
+ return Time;
}
/*
- @unimplemented
+ @implemented
*/
-KSDDKAPI VOID NTAPI
+KSDDKAPI
+VOID
+NTAPI
KsSetDefaultClockTime(
IN PKSDEFAULTCLOCK DefaultClock,
IN LONGLONG Time)
{
- UNIMPLEMENTED;
+ PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
+
+ /* set the time safely */
+ ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
}