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