[NTOS:MM] Implement and use MiAcquirePfnLockAtDpcLevel/MiReleasePfnLockFromDpcLevel.
[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 #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 }