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