[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / clocks.c
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 "priv.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 implemention 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 implemention 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 return STATUS_INSUFFICIENT_RESOURCES;
399
400 /* now allocate the object header */
401 Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
402
403 /* did it work */
404 if (!NT_SUCCESS(Status))
405 {
406 /* failed */
407 FreeItem(Clock);
408 return Status;
409 }
410
411 /* initialize clock */
412 /* FIXME IKsClock */
413 Clock->ObjectHeader->ObjectType = (PVOID)Clock;
414 Clock->ref = 1;
415 Clock->ClockCreate = ClockCreate;
416 Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
417
418 /* increment reference count */
419 InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
420
421 return Status;
422 }
423
424 /*
425 @implemented
426 */
427 KSDDKAPI
428 NTSTATUS
429 NTAPI
430 KsAllocateDefaultClock(
431 OUT PKSDEFAULTCLOCK* DefaultClock)
432 {
433 return KsAllocateDefaultClockEx(DefaultClock, NULL, NULL, NULL, NULL, NULL, 0);
434 }
435
436 /*
437 @unimplemented
438 */
439 KSDDKAPI
440 NTSTATUS
441 NTAPI
442 KsAllocateDefaultClockEx(
443 OUT PKSDEFAULTCLOCK* DefaultClock,
444 IN PVOID Context OPTIONAL,
445 IN PFNKSSETTIMER SetTimer OPTIONAL,
446 IN PFNKSCANCELTIMER CancelTimer OPTIONAL,
447 IN PFNKSCORRELATEDTIME CorrelatedTime OPTIONAL,
448 IN const KSRESOLUTION* Resolution OPTIONAL,
449 IN ULONG Flags)
450 {
451 PKSIDEFAULTCLOCK Clock;
452
453 if (!DefaultClock)
454 return STATUS_INVALID_PARAMETER_1;
455
456 /* allocate default clock */
457 Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
458 if (!Clock)
459 return STATUS_INSUFFICIENT_RESOURCES;
460
461 /* initialize default clock */
462 KeInitializeSpinLock(&Clock->TimeLock);
463 KeInitializeTimer(&Clock->Timer);
464 Clock->ReferenceCount = 1;
465 Clock->Context = Context;
466 Clock->SetTimer = SetTimer;
467 Clock->CancelTimer = CancelTimer;
468 Clock->CorrelatedTime = CorrelatedTime;
469 Clock->Flags = Flags;
470
471 if (Resolution)
472 {
473 if (SetTimer)
474 {
475 Clock->Error = Resolution->Error;
476 }
477
478 if (CorrelatedTime)
479 {
480 Clock->Granularity = Resolution->Granularity;
481 }
482 }
483
484 *DefaultClock = (PKSDEFAULTCLOCK)Clock;
485 return STATUS_SUCCESS;
486 }
487
488 /*
489 @implemented
490 */
491 KSDDKAPI
492 VOID
493 NTAPI
494 KsFreeDefaultClock(
495 IN PKSDEFAULTCLOCK DefaultClock)
496 {
497 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
498
499 InterlockedDecrement(&Clock->ReferenceCount);
500
501 if (Clock->ReferenceCount == 0)
502 {
503 /* free default clock */
504 FreeItem(Clock);
505 }
506 }
507
508 /*
509 @implemented
510 */
511 KSDDKAPI
512 KSSTATE
513 NTAPI
514 KsGetDefaultClockState(
515 IN PKSDEFAULTCLOCK DefaultClock)
516 {
517 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
518 return Clock->State;
519 }
520
521 /*
522 @unimplemented
523 */
524 KSDDKAPI
525 VOID
526 NTAPI
527 KsSetDefaultClockState(
528 IN PKSDEFAULTCLOCK DefaultClock,
529 IN KSSTATE State)
530 {
531 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
532
533 if (State != Clock->State)
534 {
535 /* FIXME set time etc */
536 Clock->State = State;
537 }
538
539 }
540
541 /*
542 @implemented
543 */
544 KSDDKAPI
545 LONGLONG
546 NTAPI
547 KsGetDefaultClockTime(
548 IN PKSDEFAULTCLOCK DefaultClock)
549 {
550 LONGLONG Time = 0LL;
551 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
552
553 Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
554
555 return Time;
556 }
557
558 /*
559 @implemented
560 */
561 KSDDKAPI
562 VOID
563 NTAPI
564 KsSetDefaultClockTime(
565 IN PKSDEFAULTCLOCK DefaultClock,
566 IN LONGLONG Time)
567 {
568 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
569
570 /* set the time safely */
571 ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
572 }