xref: /reactos/drivers/ksfilter/ks/clocks.c (revision 1734f297)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/ksfilter/ks/clocks.c
5  * PURPOSE:         KS Clocks functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 typedef struct
15 {
16     LONGLONG Time;
17     KSPIN_LOCK TimeLock;
18     KSSTATE State;
19     KTIMER Timer;
20     LONG ReferenceCount;
21 
22     PVOID Context;
23     PFNKSSETTIMER SetTimer;
24     PFNKSCANCELTIMER CancelTimer;
25     PFNKSCORRELATEDTIME CorrelatedTime;
26     LONGLONG Granularity;
27     LONGLONG Error;
28     ULONG Flags;
29 
30 }KSIDEFAULTCLOCK, *PKSIDEFAULTCLOCK;
31 
32 typedef struct
33 {
34     LONG ref;
35     PKSCLOCK_CREATE ClockCreate;
36     PKSIDEFAULTCLOCK DefaultClock;
37     PKSIOBJECT_HEADER ObjectHeader;
38 }KSICLOCK, *PKSICLOCK;
39 
40 NTSTATUS NTAPI ClockPropertyTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
41 NTSTATUS NTAPI ClockPropertyPhysicalTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
42 NTSTATUS NTAPI ClockPropertyCorrelatedTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
43 NTSTATUS NTAPI ClockPropertyCorrelatedPhysicalTime(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
44 NTSTATUS NTAPI ClockPropertyResolution(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
45 NTSTATUS NTAPI ClockPropertyState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
46 NTSTATUS NTAPI ClockPropertyFunctionTable(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
47 
48 DEFINE_KSPROPERTY_CLOCKSET(ClockPropertyTable, ClockPropertyTime, ClockPropertyPhysicalTime, ClockPropertyCorrelatedTime, ClockPropertyCorrelatedPhysicalTime, ClockPropertyResolution, ClockPropertyState, ClockPropertyFunctionTable);
49 
50 KSPROPERTY_SET ClockPropertySet[] =
51 {
52     {
53         &KSPROPSETID_Clock,
54         sizeof(ClockPropertyTable) / sizeof(KSPROPERTY_ITEM),
55         (const KSPROPERTY_ITEM*)&ClockPropertyTable,
56         0,
57         NULL
58     }
59 };
60 
61 LONGLONG
62 FASTCALL
63 ClockGetPhysicalTime(
64     IN PFILE_OBJECT FileObject)
65 {
66     UNIMPLEMENTED;
67     return 0;
68 }
69 
70 LONGLONG
71 FASTCALL
72 ClockGetCorrelatedTime(
73     IN PFILE_OBJECT FileObject,
74     OUT PLONGLONG SystemTime)
75 {
76     UNIMPLEMENTED;
77     return 0;
78 }
79 
80 LONGLONG
81 FASTCALL
82 ClockGetTime(
83     IN PFILE_OBJECT FileObject)
84 {
85     UNIMPLEMENTED;
86     return 0;
87 }
88 
89 LONGLONG
90 FASTCALL
91 ClockGetCorrelatedPhysicalTime(
92     IN PFILE_OBJECT FileObject,
93     OUT PLONGLONG SystemTime)
94 {
95     UNIMPLEMENTED;
96     return 0;
97 }
98 
99 NTSTATUS
100 NTAPI
101 ClockPropertyTime(
102     IN PIRP Irp,
103     IN PKSIDENTIFIER Request,
104     IN OUT PVOID Data)
105 {
106     PLONGLONG Time = (PLONGLONG)Data;
107     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
108 
109     DPRINT("ClockPropertyTime\n");
110 
111     *Time = ClockGetTime(IoStack->FileObject);
112 
113     Irp->IoStatus.Information = sizeof(LONGLONG);
114     return STATUS_SUCCESS;
115 }
116 
117 NTSTATUS
118 NTAPI
119 ClockPropertyPhysicalTime(
120     IN PIRP Irp,
121     IN PKSIDENTIFIER Request,
122     IN OUT PVOID Data)
123 {
124     PLONGLONG Time = (PLONGLONG)Data;
125     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
126 
127     DPRINT("ClockPropertyPhysicalTime\n");
128 
129     *Time = ClockGetPhysicalTime(IoStack->FileObject);
130 
131     Irp->IoStatus.Information = sizeof(LONGLONG);
132     return STATUS_SUCCESS;
133 }
134 
135 NTSTATUS
136 NTAPI
137 ClockPropertyCorrelatedTime(
138     IN PIRP Irp,
139     IN PKSIDENTIFIER Request,
140     IN OUT PVOID Data)
141 {
142     PKSCORRELATED_TIME Time = (PKSCORRELATED_TIME)Data;
143     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
144 
145     DPRINT("ClockPropertyCorrelatedTime\n");
146 
147     Time->Time = ClockGetCorrelatedTime(IoStack->FileObject, &Time->SystemTime);
148 
149     Irp->IoStatus.Information = sizeof(KSCORRELATED_TIME);
150     return STATUS_SUCCESS;
151 }
152 
153 NTSTATUS
154 NTAPI
155 ClockPropertyCorrelatedPhysicalTime(
156     IN PIRP Irp,
157     IN PKSIDENTIFIER Request,
158     IN OUT PVOID Data)
159 {
160     PKSCORRELATED_TIME Time = (PKSCORRELATED_TIME)Data;
161     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
162 
163     DPRINT("ClockPropertyCorrelatedPhysicalTime\n");
164 
165     Time->Time = ClockGetCorrelatedPhysicalTime(IoStack->FileObject, &Time->SystemTime);
166 
167     Irp->IoStatus.Information = sizeof(KSCORRELATED_TIME);
168     return STATUS_SUCCESS;
169 }
170 
171 NTSTATUS
172 NTAPI
173 ClockPropertyResolution(
174     IN PIRP Irp,
175     IN PKSIDENTIFIER Request,
176     IN OUT PVOID Data)
177 {
178     PKSICLOCK Clock;
179     PKSIOBJECT_HEADER ObjectHeader;
180     PIO_STACK_LOCATION IoStack;
181     PKSRESOLUTION Resolution = (PKSRESOLUTION)Data;
182 
183     DPRINT("ClockPropertyResolution\n");
184 
185     /* get stack location */
186     IoStack = IoGetCurrentIrpStackLocation(Irp);
187 
188     /* get the object header */
189     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
190 
191     /* sanity check */
192     ASSERT(ObjectHeader);
193 
194     /* locate ks pin implementation from KSPIN offset */
195     Clock = (PKSICLOCK)ObjectHeader->ObjectType;
196 
197     Resolution->Error = Clock->DefaultClock->Error;
198     Resolution->Granularity = Clock->DefaultClock->Granularity;
199 
200     Irp->IoStatus.Information = sizeof(KSRESOLUTION);
201     return STATUS_SUCCESS;
202 }
203 
204 NTSTATUS
205 NTAPI
206 ClockPropertyState(
207     IN PIRP Irp,
208     IN PKSIDENTIFIER Request,
209     IN OUT PVOID Data)
210 {
211     PKSICLOCK Clock;
212     PKSIOBJECT_HEADER ObjectHeader;
213     PKSSTATE State = (PKSSTATE)Data;
214     PIO_STACK_LOCATION IoStack;
215 
216     DPRINT("ClockPropertyState\n");
217 
218     /* get stack location */
219     IoStack = IoGetCurrentIrpStackLocation(Irp);
220 
221     /* get the object header */
222     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
223 
224     /* sanity check */
225     ASSERT(ObjectHeader);
226 
227     /* locate ks pin implementation from KSPIN offset */
228     Clock = (PKSICLOCK)ObjectHeader->ObjectType;
229 
230     *State = Clock->DefaultClock->State;
231     Irp->IoStatus.Information = sizeof(KSSTATE);
232 
233     return STATUS_SUCCESS;
234 }
235 
236 NTSTATUS
237 NTAPI
238 ClockPropertyFunctionTable(
239     IN PIRP Irp,
240     IN PKSIDENTIFIER Request,
241     IN OUT PVOID Data)
242 {
243     PKSCLOCK_FUNCTIONTABLE Table = (PKSCLOCK_FUNCTIONTABLE)Data;
244 
245     DPRINT("ClockPropertyFunctionTable\n");
246 
247     Table->GetCorrelatedPhysicalTime = ClockGetCorrelatedPhysicalTime;
248     Table->GetCorrelatedTime = ClockGetCorrelatedTime;
249     Table->GetPhysicalTime = ClockGetPhysicalTime;
250     Table->GetTime = ClockGetTime;
251 
252     return STATUS_SUCCESS;
253 }
254 
255 
256 /*
257     @implemented
258 */
259 KSDDKAPI NTSTATUS NTAPI
260 KsCreateClock(
261     IN  HANDLE ConnectionHandle,
262     IN  PKSCLOCK_CREATE ClockCreate,
263     OUT PHANDLE ClockHandle)
264 {
265     return KspCreateObjectType(ConnectionHandle,
266                                KSSTRING_Clock,
267                                ClockCreate,
268                                sizeof(KSCLOCK_CREATE),
269                                GENERIC_READ,
270                                ClockHandle);
271 }
272 
273 /*
274     @implemented
275 */
276 KSDDKAPI
277 NTSTATUS
278 NTAPI
279 KsValidateClockCreateRequest(
280     IN  PIRP Irp,
281     OUT PKSCLOCK_CREATE* OutClockCreate)
282 {
283     PKSCLOCK_CREATE ClockCreate;
284     NTSTATUS Status;
285     ULONG Size;
286 
287     /* minimum request size */
288     Size = sizeof(KSCLOCK_CREATE);
289 
290     /* copy create request */
291     Status = KspCopyCreateRequest(Irp,
292                                   KSSTRING_Clock,
293                                   &Size,
294                                   (PVOID*)&ClockCreate);
295 
296     if (!NT_SUCCESS(Status))
297         return Status;
298 
299     if (ClockCreate->CreateFlags != 0)
300     {
301         /* flags must be zero */
302         FreeItem(ClockCreate);
303         return STATUS_INVALID_PARAMETER;
304     }
305 
306     *OutClockCreate = ClockCreate;
307     return STATUS_SUCCESS;
308 }
309 
310 NTSTATUS
311 NTAPI
312 IKsClock_DispatchDeviceIoControl(
313     IN PDEVICE_OBJECT DeviceObject,
314     IN  PIRP Irp)
315 {
316     PIO_STACK_LOCATION IoStack;
317     UNICODE_STRING GuidString;
318     PKSPROPERTY Property;
319     NTSTATUS Status;
320 
321     DPRINT("IKsClock_DispatchDeviceIoControl\n");
322 
323     /* get current io stack */
324     IoStack = IoGetCurrentIrpStackLocation(Irp);
325 
326     /* FIXME support events */
327     ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
328 
329     /* sanity check */
330     ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSPROPERTY));
331 
332     /* call property handler */
333     Status = KsPropertyHandler(Irp, 1, ClockPropertySet);
334 
335     /* get property from input buffer */
336     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
337 
338     RtlStringFromGUID(&Property->Set, &GuidString);
339     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);
340     RtlFreeUnicodeString(&GuidString);
341 
342 
343     Irp->IoStatus.Status = STATUS_SUCCESS;
344     CompleteRequest(Irp, IO_NO_INCREMENT);
345 
346     return STATUS_SUCCESS;
347 }
348 
349 NTSTATUS
350 NTAPI
351 IKsClock_DispatchClose(
352     IN PDEVICE_OBJECT DeviceObject,
353     IN  PIRP Irp)
354 {
355     UNIMPLEMENTED;
356 
357     Irp->IoStatus.Status = STATUS_SUCCESS;
358     CompleteRequest(Irp, IO_NO_INCREMENT);
359 
360     return STATUS_SUCCESS;
361 }
362 
363 static KSDISPATCH_TABLE DispatchTable =
364 {
365     IKsClock_DispatchDeviceIoControl,
366     KsDispatchInvalidDeviceRequest,
367     KsDispatchInvalidDeviceRequest,
368     KsDispatchInvalidDeviceRequest,
369     IKsClock_DispatchClose,
370     KsDispatchQuerySecurity,
371     KsDispatchSetSecurity,
372     KsDispatchFastIoDeviceControlFailure,
373     KsDispatchFastReadFailure,
374     KsDispatchFastReadFailure,
375 };
376 
377 /*
378     @implemented
379 */
380 KSDDKAPI
381 NTSTATUS
382 NTAPI
383 KsCreateDefaultClock(
384     IN  PIRP Irp,
385     IN  PKSDEFAULTCLOCK DefaultClock)
386 {
387     NTSTATUS Status;
388     PKSCLOCK_CREATE ClockCreate;
389     PKSICLOCK Clock;
390 
391     Status = KsValidateClockCreateRequest(Irp, &ClockCreate);
392     if (!NT_SUCCESS(Status))
393         return Status;
394 
395     /* let's allocate the clock struct */
396     Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
397     if (!Clock)
398     {
399         FreeItem(ClockCreate);
400         return STATUS_INSUFFICIENT_RESOURCES;
401     }
402 
403     /* now allocate the object header */
404     Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
405 
406     /* did it work */
407     if (!NT_SUCCESS(Status))
408     {
409         /* failed */
410         FreeItem(ClockCreate);
411         FreeItem(Clock);
412         return Status;
413     }
414 
415     /* initialize clock */
416     /* FIXME IKsClock */
417     Clock->ObjectHeader->ObjectType = (PVOID)Clock;
418     Clock->ref = 1;
419     Clock->ClockCreate = ClockCreate;
420     Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
421 
422     /* increment reference count */
423     InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
424 
425     return Status;
426 }
427 
428 /*
429     @implemented
430 */
431 KSDDKAPI
432 NTSTATUS
433 NTAPI
434 KsAllocateDefaultClock(
435     OUT PKSDEFAULTCLOCK* DefaultClock)
436 {
437     return KsAllocateDefaultClockEx(DefaultClock, NULL, NULL, NULL, NULL, NULL, 0);
438 }
439 
440 /*
441     @unimplemented
442 */
443 KSDDKAPI
444 NTSTATUS
445 NTAPI
446 KsAllocateDefaultClockEx(
447     OUT PKSDEFAULTCLOCK* DefaultClock,
448     IN  PVOID Context OPTIONAL,
449     IN  PFNKSSETTIMER SetTimer OPTIONAL,
450     IN  PFNKSCANCELTIMER CancelTimer OPTIONAL,
451     IN  PFNKSCORRELATEDTIME CorrelatedTime OPTIONAL,
452     IN  const KSRESOLUTION* Resolution OPTIONAL,
453     IN  ULONG Flags)
454 {
455     PKSIDEFAULTCLOCK Clock;
456 
457     if (!DefaultClock)
458        return STATUS_INVALID_PARAMETER_1;
459 
460     /* allocate default clock */
461     Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
462     if (!Clock)
463         return STATUS_INSUFFICIENT_RESOURCES;
464 
465     /* initialize default clock */
466     KeInitializeSpinLock(&Clock->TimeLock);
467     KeInitializeTimer(&Clock->Timer);
468     Clock->ReferenceCount = 1;
469     Clock->Context = Context;
470     Clock->SetTimer = SetTimer;
471     Clock->CancelTimer = CancelTimer;
472     Clock->CorrelatedTime = CorrelatedTime;
473     Clock->Flags = Flags;
474 
475     if (Resolution)
476     {
477         if (SetTimer)
478         {
479             Clock->Error = Resolution->Error;
480         }
481 
482         if (CorrelatedTime)
483         {
484             Clock->Granularity = Resolution->Granularity;
485         }
486     }
487 
488     *DefaultClock = (PKSDEFAULTCLOCK)Clock;
489     return STATUS_SUCCESS;
490 }
491 
492 /*
493     @implemented
494 */
495 KSDDKAPI
496 VOID
497 NTAPI
498 KsFreeDefaultClock(
499     IN  PKSDEFAULTCLOCK DefaultClock)
500 {
501     PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
502 
503     InterlockedDecrement(&Clock->ReferenceCount);
504 
505     if (Clock->ReferenceCount == 0)
506     {
507         /* free default clock */
508         FreeItem(Clock);
509     }
510 }
511 
512 /*
513     @implemented
514 */
515 KSDDKAPI
516 KSSTATE
517 NTAPI
518 KsGetDefaultClockState(
519     IN  PKSDEFAULTCLOCK DefaultClock)
520 {
521     PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
522     return Clock->State;
523 }
524 
525 /*
526     @unimplemented
527 */
528 KSDDKAPI
529 VOID
530 NTAPI
531 KsSetDefaultClockState(
532     IN  PKSDEFAULTCLOCK DefaultClock,
533     IN  KSSTATE State)
534 {
535     PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
536 
537     if (State != Clock->State)
538     {
539          /* FIXME set time etc */
540          Clock->State = State;
541     }
542 
543 }
544 
545 /*
546     @implemented
547 */
548 KSDDKAPI
549 LONGLONG
550 NTAPI
551 KsGetDefaultClockTime(
552     IN  PKSDEFAULTCLOCK DefaultClock)
553 {
554     LONGLONG Time = 0LL;
555     PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
556 
557     Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
558 
559     return Time;
560 }
561 
562 /*
563     @implemented
564 */
565 KSDDKAPI
566 VOID
567 NTAPI
568 KsSetDefaultClockTime(
569     IN  PKSDEFAULTCLOCK DefaultClock,
570     IN  LONGLONG Time)
571 {
572     PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
573 
574     /* set the time safely */
575     ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
576 }
577