[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / clocks.c
index bc34145..05064be 100644 (file)
+/*
+ * 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;
+
+}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(
@@ -14,36 +260,171 @@ 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)
 {
@@ -53,7 +434,9 @@ KsAllocateDefaultClock(
 /*
     @unimplemented
 */
-KSDDKAPI NTSTATUS NTAPI
+KSDDKAPI
+NTSTATUS
+NTAPI
 KsAllocateDefaultClockEx(
     OUT PKSDEFAULTCLOCK* DefaultClock,
     IN  PVOID Context OPTIONAL,
@@ -63,72 +446,125 @@ KsAllocateDefaultClockEx(
     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);
 }