1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/ksfilter/ks/factory.c 5 * PURPOSE: KS Allocator functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 #include <ntifs.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* 17 @implemented 18 */ 19 KSDDKAPI 20 NTSTATUS 21 NTAPI 22 KsDispatchQuerySecurity( 23 IN PDEVICE_OBJECT DeviceObject, 24 IN PIRP Irp) 25 { 26 PKSOBJECT_CREATE_ITEM CreateItem; 27 PIO_STACK_LOCATION IoStack; 28 NTSTATUS Status; 29 ULONG Length; 30 31 /* get current irp stack */ 32 IoStack = IoGetCurrentIrpStackLocation(Irp); 33 34 /* get create item */ 35 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); 36 37 if (!CreateItem || !CreateItem->SecurityDescriptor) 38 { 39 /* no create item */ 40 Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; 41 CompleteRequest(Irp, IO_NO_INCREMENT); 42 return STATUS_NO_SECURITY_ON_OBJECT; 43 } 44 45 46 /* get input length */ 47 Length = IoStack->Parameters.QuerySecurity.Length; 48 49 /* clone the security descriptor */ 50 Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)Irp->UserBuffer, &Length, &CreateItem->SecurityDescriptor); 51 52 DPRINT("SeQuerySecurityDescriptorInfo Status %x\n", Status); 53 /* store result */ 54 Irp->IoStatus.Status = Status; 55 Irp->IoStatus.Information = Length; 56 57 CompleteRequest(Irp, IO_NO_INCREMENT); 58 return Status; 59 } 60 61 /* 62 @implemented 63 */ 64 KSDDKAPI 65 NTSTATUS 66 NTAPI 67 KsDispatchSetSecurity( 68 IN PDEVICE_OBJECT DeviceObject, 69 IN PIRP Irp) 70 { 71 PKSOBJECT_CREATE_ITEM CreateItem; 72 PIO_STACK_LOCATION IoStack; 73 PGENERIC_MAPPING Mapping; 74 PSECURITY_DESCRIPTOR Descriptor; 75 NTSTATUS Status; 76 77 /* get current irp stack */ 78 IoStack = IoGetCurrentIrpStackLocation(Irp); 79 80 /* get create item */ 81 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); 82 83 if (!CreateItem || !CreateItem->SecurityDescriptor) 84 { 85 /* no create item */ 86 Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT; 87 CompleteRequest(Irp, IO_NO_INCREMENT); 88 return STATUS_NO_SECURITY_ON_OBJECT; 89 } 90 91 /* backup old descriptor */ 92 Descriptor = CreateItem->SecurityDescriptor; 93 94 /* get generic mapping */ 95 Mapping = IoGetFileObjectGenericMapping(); 96 97 /* change security descriptor */ 98 Status = SeSetSecurityDescriptorInfo(NULL, /*FIXME */ 99 &IoStack->Parameters.SetSecurity.SecurityInformation, 100 IoStack->Parameters.SetSecurity.SecurityDescriptor, 101 &CreateItem->SecurityDescriptor, 102 NonPagedPool, 103 Mapping); 104 105 if (NT_SUCCESS(Status)) 106 { 107 /* free old descriptor */ 108 FreeItem(Descriptor); 109 110 /* mark create item as changed */ 111 CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED; 112 } 113 114 /* store result */ 115 Irp->IoStatus.Status = Status; 116 CompleteRequest(Irp, IO_NO_INCREMENT); 117 118 return Status; 119 } 120 121 /* 122 @unimplemented 123 */ 124 KSDDKAPI 125 NTSTATUS 126 NTAPI 127 KsDispatchSpecificMethod( 128 IN PIRP Irp, 129 IN PFNKSHANDLER Handler) 130 { 131 UNIMPLEMENTED; 132 return STATUS_UNSUCCESSFUL; 133 } 134 135 136 /* 137 @implemented 138 */ 139 KSDDKAPI 140 NTSTATUS 141 NTAPI 142 KsReadFile( 143 IN PFILE_OBJECT FileObject, 144 IN PKEVENT Event OPTIONAL, 145 IN PVOID PortContext OPTIONAL, 146 OUT PIO_STATUS_BLOCK IoStatusBlock, 147 OUT PVOID Buffer, 148 IN ULONG Length, 149 IN ULONG Key OPTIONAL, 150 IN KPROCESSOR_MODE RequestorMode) 151 { 152 PDEVICE_OBJECT DeviceObject; 153 PIRP Irp; 154 NTSTATUS Status; 155 BOOLEAN Result; 156 KEVENT LocalEvent; 157 158 if (Event) 159 { 160 /* make sure event is reset */ 161 KeClearEvent(Event); 162 } 163 164 if (RequestorMode == UserMode) 165 { 166 /* probe the user buffer */ 167 _SEH2_TRY 168 { 169 ProbeForWrite(Buffer, Length, sizeof(UCHAR)); 170 Status = STATUS_SUCCESS; 171 } 172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 173 { 174 /* Exception, get the error code */ 175 Status = _SEH2_GetExceptionCode(); 176 } 177 _SEH2_END; 178 179 if (!NT_SUCCESS(Status)) 180 { 181 DPRINT1("Invalid user buffer provided\n"); 182 return Status; 183 } 184 } 185 186 /* get corresponding device object */ 187 DeviceObject = IoGetRelatedDeviceObject(FileObject); 188 189 /* fast-io read is only available for kernel mode clients */ 190 if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode && 191 DeviceObject->DriverObject->FastIoDispatch->FastIoRead) 192 { 193 /* call fast io write */ 194 Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject); 195 196 if (Result && NT_SUCCESS(IoStatusBlock->Status)) 197 { 198 /* request was handled and succeeded */ 199 return STATUS_SUCCESS; 200 } 201 } 202 203 /* do the slow way */ 204 if (!Event) 205 { 206 /* initialize temp event */ 207 KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE); 208 Event = &LocalEvent; 209 } 210 211 /* build the irp packet */ 212 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock); 213 if (!Irp) 214 { 215 /* not enough resources */ 216 return STATUS_INSUFFICIENT_RESOURCES; 217 } 218 219 /* send the packet */ 220 Status = IoCallDriver(DeviceObject, Irp); 221 222 if (Status == STATUS_PENDING) 223 { 224 /* operation is pending, is sync file object */ 225 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 226 { 227 /* it is so wait */ 228 KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL); 229 Status = IoStatusBlock->Status; 230 } 231 } 232 /* return result */ 233 return Status; 234 } 235 236 /* 237 @implemented 238 */ 239 KSDDKAPI 240 NTSTATUS 241 NTAPI 242 KsWriteFile( 243 IN PFILE_OBJECT FileObject, 244 IN PKEVENT Event OPTIONAL, 245 IN PVOID PortContext OPTIONAL, 246 OUT PIO_STATUS_BLOCK IoStatusBlock, 247 IN PVOID Buffer, 248 IN ULONG Length, 249 IN ULONG Key OPTIONAL, 250 IN KPROCESSOR_MODE RequestorMode) 251 { 252 PDEVICE_OBJECT DeviceObject; 253 PIRP Irp; 254 NTSTATUS Status; 255 BOOLEAN Result; 256 KEVENT LocalEvent; 257 258 if (Event) 259 { 260 /* make sure event is reset */ 261 KeClearEvent(Event); 262 } 263 264 if (RequestorMode == UserMode) 265 { 266 /* probe the user buffer */ 267 _SEH2_TRY 268 { 269 ProbeForRead(Buffer, Length, sizeof(UCHAR)); 270 Status = STATUS_SUCCESS; 271 } 272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 273 { 274 /* Exception, get the error code */ 275 Status = _SEH2_GetExceptionCode(); 276 } 277 _SEH2_END; 278 279 if (!NT_SUCCESS(Status)) 280 { 281 DPRINT1("Invalid user buffer provided\n"); 282 return Status; 283 } 284 } 285 286 /* get corresponding device object */ 287 DeviceObject = IoGetRelatedDeviceObject(FileObject); 288 289 /* fast-io write is only available for kernel mode clients */ 290 if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode && 291 DeviceObject->DriverObject->FastIoDispatch->FastIoWrite) 292 { 293 /* call fast io write */ 294 Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject); 295 296 if (Result && NT_SUCCESS(IoStatusBlock->Status)) 297 { 298 /* request was handled and succeeded */ 299 return STATUS_SUCCESS; 300 } 301 } 302 303 /* do the slow way */ 304 if (!Event) 305 { 306 /* initialize temp event */ 307 KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE); 308 Event = &LocalEvent; 309 } 310 311 /* build the irp packet */ 312 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock); 313 if (!Irp) 314 { 315 /* not enough resources */ 316 return STATUS_INSUFFICIENT_RESOURCES; 317 } 318 319 /* send the packet */ 320 Status = IoCallDriver(DeviceObject, Irp); 321 322 if (Status == STATUS_PENDING) 323 { 324 /* operation is pending, is sync file object */ 325 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 326 { 327 /* it is so wait */ 328 KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL); 329 Status = IoStatusBlock->Status; 330 } 331 } 332 /* return result */ 333 return Status; 334 } 335 336 /* 337 @implemented 338 */ 339 KSDDKAPI 340 NTSTATUS 341 NTAPI 342 KsQueryInformationFile( 343 IN PFILE_OBJECT FileObject, 344 OUT PVOID FileInformation, 345 IN ULONG Length, 346 IN FILE_INFORMATION_CLASS FileInformationClass) 347 { 348 PDEVICE_OBJECT DeviceObject; 349 PFAST_IO_DISPATCH FastIoDispatch; 350 PIRP Irp; 351 PIO_STACK_LOCATION IoStack; 352 IO_STATUS_BLOCK IoStatusBlock; 353 KEVENT Event; 354 LARGE_INTEGER Offset; 355 NTSTATUS Status; 356 357 /* get related file object */ 358 DeviceObject = IoGetRelatedDeviceObject(FileObject); 359 360 /* get fast i/o table */ 361 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch; 362 363 /* is there a fast table */ 364 if (FastIoDispatch) 365 { 366 /* check the class */ 367 if (FileInformationClass == FileBasicInformation) 368 { 369 /* use FastIoQueryBasicInfo routine */ 370 if (FastIoDispatch->FastIoQueryBasicInfo != NULL && 371 FastIoDispatch->FastIoQueryBasicInfo( 372 FileObject, 373 TRUE, 374 (PFILE_BASIC_INFORMATION)FileInformation, 375 &IoStatusBlock, 376 DeviceObject)) 377 { 378 /* request was handled */ 379 return IoStatusBlock.Status; 380 } 381 } 382 else if (FileInformationClass == FileStandardInformation) 383 { 384 /* use FastIoQueryStandardInfo routine */ 385 if (FastIoDispatch->FastIoQueryStandardInfo != NULL && 386 FastIoDispatch->FastIoQueryStandardInfo( 387 FileObject, 388 TRUE, 389 (PFILE_STANDARD_INFORMATION)FileInformation, 390 &IoStatusBlock, 391 DeviceObject)) 392 { 393 /* request was handled */ 394 return IoStatusBlock.Status; 395 } 396 } 397 } 398 399 /* clear event */ 400 KeClearEvent(&FileObject->Event); 401 402 /* initialize event */ 403 KeInitializeEvent(&Event, NotificationEvent, FALSE); 404 405 /* set offset to zero */ 406 Offset.QuadPart = 0L; 407 408 /* build the request */ 409 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &IoStatusBlock); 410 if (!Irp) 411 return STATUS_INSUFFICIENT_RESOURCES; 412 413 /* get next stack location */ 414 IoStack = IoGetNextIrpStackLocation(Irp); 415 416 /* setup parameters */ 417 IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass; 418 IoStack->Parameters.QueryFile.Length = Length; 419 Irp->AssociatedIrp.SystemBuffer = FileInformation; 420 421 422 /* call the driver */ 423 Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); 424 425 if (Status == STATUS_PENDING) 426 { 427 /* wait for the operation to complete */ 428 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 429 430 /* is object sync */ 431 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 432 Status = FileObject->FinalStatus; 433 else 434 Status = IoStatusBlock.Status; 435 } 436 437 /* done */ 438 return Status; 439 } 440 441 /* 442 @implemented 443 */ 444 KSDDKAPI 445 NTSTATUS 446 NTAPI 447 KsSetInformationFile( 448 IN PFILE_OBJECT FileObject, 449 IN PVOID FileInformation, 450 IN ULONG Length, 451 IN FILE_INFORMATION_CLASS FileInformationClass) 452 { 453 PIO_STACK_LOCATION IoStack; 454 PDEVICE_OBJECT DeviceObject; 455 PIRP Irp; 456 PVOID Buffer; 457 KEVENT Event; 458 LARGE_INTEGER Offset; 459 IO_STATUS_BLOCK IoStatus; 460 NTSTATUS Status; 461 462 /* get related device object */ 463 DeviceObject = IoGetRelatedDeviceObject(FileObject); 464 465 /* copy file information */ 466 Buffer = AllocateItem(NonPagedPool, Length); 467 if (!Buffer) 468 return STATUS_INSUFFICIENT_RESOURCES; 469 470 _SEH2_TRY 471 { 472 ProbeForRead(Buffer, Length, sizeof(UCHAR)); 473 RtlMoveMemory(Buffer, FileInformation, Length); 474 Status = STATUS_SUCCESS; 475 } 476 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 477 { 478 /* Exception, get the error code */ 479 Status = _SEH2_GetExceptionCode(); 480 } 481 _SEH2_END; 482 483 if (!NT_SUCCESS(Status)) 484 { 485 /* invalid user buffer */ 486 FreeItem(Buffer); 487 return Status; 488 } 489 490 /* initialize the event */ 491 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 492 493 /* zero offset */ 494 Offset.QuadPart = 0LL; 495 496 /* build the irp */ 497 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus); 498 if (!Irp) 499 { 500 /* failed to allocate irp */ 501 FreeItem(Buffer); 502 return STATUS_INSUFFICIENT_RESOURCES; 503 } 504 505 /* get next stack location */ 506 IoStack = IoGetNextIrpStackLocation(Irp); 507 508 /* set irp parameters */ 509 IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass; 510 IoStack->Parameters.SetFile.Length = Length; 511 IoStack->Parameters.SetFile.FileObject = FileObject; 512 Irp->AssociatedIrp.SystemBuffer = Buffer; 513 Irp->UserBuffer = FileInformation; 514 515 /* dispatch the irp */ 516 Status = IoCallDriver(DeviceObject, Irp); 517 518 if (Status == STATUS_PENDING) 519 { 520 /* wait untill the operation has completed */ 521 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 522 /* is a sync file object */ 523 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 524 Status = FileObject->FinalStatus; 525 else 526 Status = IoStatus.Status; 527 } 528 /* done */ 529 return Status; 530 } 531 532 /* 533 @implemented 534 */ 535 KSDDKAPI 536 NTSTATUS 537 NTAPI 538 KsStreamIo( 539 IN PFILE_OBJECT FileObject, 540 IN PKEVENT Event OPTIONAL, 541 IN PVOID PortContext OPTIONAL, 542 IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL, 543 IN PVOID CompletionContext OPTIONAL, 544 IN KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL, 545 OUT PIO_STATUS_BLOCK IoStatusBlock, 546 IN OUT PVOID StreamHeaders, 547 IN ULONG Length, 548 IN ULONG Flags, 549 IN KPROCESSOR_MODE RequestorMode) 550 { 551 PIRP Irp; 552 PIO_STACK_LOCATION IoStack; 553 PDEVICE_OBJECT DeviceObject; 554 NTSTATUS Status; 555 LARGE_INTEGER Offset; 556 PKSIOBJECT_HEADER ObjectHeader; 557 BOOLEAN Ret; 558 559 /* get related device object */ 560 DeviceObject = IoGetRelatedDeviceObject(FileObject); 561 /* sanity check */ 562 ASSERT(DeviceObject != NULL); 563 564 /* is there a event provided */ 565 if (Event) 566 { 567 /* reset event */ 568 KeClearEvent(Event); 569 } 570 571 if (RequestorMode || ExGetPreviousMode() == KernelMode) 572 { 573 /* requestor is from kernel land */ 574 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2; 575 576 if (ObjectHeader) 577 { 578 /* there is a object header */ 579 if (Flags == KSSTREAM_READ) 580 { 581 /* is fast read supported */ 582 if (ObjectHeader->DispatchTable.FastRead) 583 { 584 /* call fast read dispatch routine */ 585 Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject); 586 587 if (Ret) 588 { 589 /* the request was handled */ 590 return IoStatusBlock->Status; 591 } 592 } 593 } 594 else if (Flags == KSSTREAM_WRITE) 595 { 596 /* is fast write supported */ 597 if (ObjectHeader->DispatchTable.FastWrite) 598 { 599 /* call fast write dispatch routine */ 600 Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject); 601 602 if (Ret) 603 { 604 /* the request was handled */ 605 return IoStatusBlock->Status; 606 } 607 } 608 } 609 } 610 } 611 612 /* clear file object event */ 613 KeClearEvent(&FileObject->Event); 614 615 /* set the offset to zero */ 616 Offset.QuadPart = 0LL; 617 618 /* now build the irp */ 619 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL, 620 DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock); 621 if (!Irp) 622 { 623 /* not enough memory */ 624 return STATUS_INSUFFICIENT_RESOURCES; 625 } 626 627 /* setup irp parameters */ 628 Irp->RequestorMode = RequestorMode; 629 Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext; 630 Irp->Tail.Overlay.OriginalFileObject = FileObject; 631 Irp->UserBuffer = StreamHeaders; 632 633 /* get next irp stack location */ 634 IoStack = IoGetNextIrpStackLocation(Irp); 635 /* setup stack parameters */ 636 IoStack->FileObject = FileObject; 637 IoStack->Parameters.DeviceIoControl.InputBufferLength = Length; 638 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders; 639 IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); 640 641 if (CompletionRoutine) 642 { 643 /* setup completion routine for async processing */ 644 IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel)); 645 } 646 647 /* now call the driver */ 648 Status = IoCallDriver(DeviceObject, Irp); 649 /* done */ 650 return Status; 651 } 652 653 /* 654 @implemented 655 */ 656 KSDDKAPI 657 NTSTATUS 658 NTAPI 659 KsProbeStreamIrp( 660 IN PIRP Irp, 661 IN ULONG ProbeFlags, 662 IN ULONG HeaderSize) 663 { 664 PMDL Mdl; 665 PVOID Buffer; 666 LOCK_OPERATION Operation; 667 NTSTATUS Status = STATUS_SUCCESS; 668 PKSSTREAM_HEADER StreamHeader; 669 PIO_STACK_LOCATION IoStack; 670 ULONG Length; 671 //BOOLEAN AllocateMdl = FALSE; 672 673 /* get current irp stack */ 674 IoStack = IoGetCurrentIrpStackLocation(Irp); 675 676 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 677 678 if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer) 679 { 680 if (Irp->RequestorMode == KernelMode) 681 { 682 /* no need to allocate stream header */ 683 Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer; 684 } 685 AllocMdl: 686 /* check if alloc mdl flag is passed */ 687 if (!(ProbeFlags & KSPROBE_ALLOCATEMDL)) 688 { 689 /* nothing more to do */ 690 return STATUS_SUCCESS; 691 } 692 if (Irp->MdlAddress) 693 { 694 ProbeMdl: 695 if (ProbeFlags & KSPROBE_PROBEANDLOCK) 696 { 697 if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL)) 698 { 699 if (ProbeFlags & KSPROBE_SYSTEMADDRESS) 700 { 701 _SEH2_TRY 702 { 703 /* loop through all mdls and probe them */ 704 Mdl = Irp->MdlAddress; 705 do 706 { 707 /* the mapping can fail */ 708 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; 709 710 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) 711 { 712 /* no need to probe these pages */ 713 Buffer = Mdl->MappedSystemVa; 714 } 715 else 716 { 717 /* probe that mdl */ 718 Buffer = MmMapLockedPages(Mdl, KernelMode); 719 } 720 721 /* check if the mapping succeeded */ 722 if (!Buffer) 723 { 724 /* raise exception we'll catch */ 725 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 726 } 727 728 /* iterate to next mdl */ 729 Mdl = Mdl->Next; 730 731 }while(Mdl); 732 } 733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 734 { 735 /* Exception, get the error code */ 736 Status = _SEH2_GetExceptionCode(); 737 } _SEH2_END; 738 } 739 } 740 else 741 { 742 _SEH2_TRY 743 { 744 /* loop through all mdls and probe them */ 745 Mdl = Irp->MdlAddress; 746 747 /* determine operation */ 748 if (!(ProbeFlags & KSPROBE_STREAMWRITE) || (ProbeFlags & KSPROBE_MODIFY)) 749 { 750 /* operation is read / modify stream, need write access */ 751 Operation = IoWriteAccess; 752 } 753 else 754 { 755 /* operation is write to device, so we need read access */ 756 Operation = IoReadAccess; 757 } 758 759 do 760 { 761 /* probe the pages */ 762 MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation); 763 764 if (ProbeFlags & KSPROBE_SYSTEMADDRESS) 765 { 766 /* the mapping can fail */ 767 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; 768 769 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) 770 { 771 /* no need to probe these pages */ 772 Buffer = Mdl->MappedSystemVa; 773 } 774 else 775 { 776 /* probe that mdl */ 777 Buffer = MmMapLockedPages(Mdl, KernelMode); 778 } 779 780 /* check if the mapping succeeded */ 781 if (!Buffer) 782 { 783 /* raise exception we'll catch */ 784 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 785 } 786 } 787 788 /* iterate to next mdl */ 789 Mdl = Mdl->Next; 790 791 }while(Mdl); 792 } 793 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 794 { 795 /* Exception, get the error code */ 796 Status = _SEH2_GetExceptionCode(); 797 } _SEH2_END; 798 } 799 } 800 return Status; 801 } 802 803 /* check all stream headers */ 804 StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; 805 ASSERT(StreamHeader); 806 _SEH2_TRY 807 { 808 do 809 { 810 if (HeaderSize) 811 { 812 /* does the supplied header size match stream header size and no type changed */ 813 if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) 814 { 815 /* invalid stream header */ 816 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 817 } 818 } 819 else 820 { 821 /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ 822 if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) 823 { 824 /* invalid stream header */ 825 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 826 } 827 } 828 829 if (Length < StreamHeader->Size) 830 { 831 /* length is too short */ 832 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 833 } 834 835 if (ProbeFlags & KSPROBE_STREAMWRITE) 836 { 837 if (StreamHeader->DataUsed > StreamHeader->FrameExtent) 838 { 839 /* frame extend can never be smaller */ 840 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 841 } 842 843 /* is this stream change packet */ 844 if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) 845 { 846 if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) 847 { 848 /* stream changed - must be send in a single packet */ 849 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 850 } 851 852 if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) 853 { 854 /* caller does not permit format changes */ 855 ExRaiseStatus(STATUS_INVALID_PARAMETER); 856 } 857 858 if (StreamHeader->FrameExtent) 859 { 860 /* allocate an mdl */ 861 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); 862 863 if (!Mdl) 864 { 865 /* not enough memory */ 866 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 867 } 868 869 /* break-out to probe for the irp */ 870 break; 871 } 872 } 873 } 874 else 875 { 876 if (StreamHeader->DataUsed) 877 { 878 /* DataUsed must be zero for stream read operation */ 879 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 880 } 881 882 if (StreamHeader->OptionsFlags) 883 { 884 /* no flags supported for reading */ 885 ExRaiseStatus(STATUS_INVALID_PARAMETER); 886 } 887 } 888 889 if (StreamHeader->FrameExtent) 890 { 891 /* allocate an mdl */ 892 ASSERT(Irp->MdlAddress == NULL); 893 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); 894 if (!Mdl) 895 { 896 /* not enough memory */ 897 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 898 } 899 } 900 901 /* move to next stream header */ 902 Length -= StreamHeader->Size; 903 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); 904 }while(Length); 905 } 906 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 907 { 908 /* Exception, get the error code */ 909 Status = _SEH2_GetExceptionCode(); 910 }_SEH2_END; 911 912 /* now probe the allocated mdl's */ 913 if (!NT_SUCCESS(Status)) 914 { 915 DPRINT("Status %x\n", Status); 916 return Status; 917 } 918 else 919 goto ProbeMdl; 920 } 921 922 /* probe user mode buffers */ 923 if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) 924 { 925 /* allocate stream header buffer */ 926 Irp->AssociatedIrp.SystemBuffer = AllocateItem(NonPagedPool, Length); 927 928 if (!Irp->AssociatedIrp.SystemBuffer) 929 { 930 /* no memory */ 931 return STATUS_INSUFFICIENT_RESOURCES; 932 } 933 934 /* mark irp as buffered so that changes the stream headers are propagated back */ 935 Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; 936 937 _SEH2_TRY 938 { 939 if (ProbeFlags & KSPROBE_STREAMWRITE) 940 { 941 if (ProbeFlags & KSPROBE_MODIFY) 942 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); 943 else 944 ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR)); 945 } 946 else 947 { 948 /* stream reads means writing */ 949 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); 950 951 /* set input operation flags */ 952 Irp->Flags |= IRP_INPUT_OPERATION; 953 } 954 955 /* copy stream buffer */ 956 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length); 957 } 958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 959 { 960 /* Exception, get the error code */ 961 Status = _SEH2_GetExceptionCode(); 962 }_SEH2_END; 963 964 if (!NT_SUCCESS(Status)) 965 { 966 /* failed */ 967 return Status; 968 } 969 970 if (ProbeFlags & KSPROBE_ALLOCATEMDL) 971 { 972 /* alloc mdls */ 973 goto AllocMdl; 974 } 975 976 /* check all stream headers */ 977 StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; 978 979 _SEH2_TRY 980 { 981 do 982 { 983 if (HeaderSize) 984 { 985 /* does the supplied header size match stream header size and no type changed */ 986 if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) 987 { 988 /* invalid stream header */ 989 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 990 } 991 } 992 else 993 { 994 /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ 995 if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) 996 { 997 /* invalid stream header */ 998 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 999 } 1000 } 1001 1002 if (Length < StreamHeader->Size) 1003 { 1004 /* length is too short */ 1005 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 1006 } 1007 1008 if (ProbeFlags & KSPROBE_STREAMWRITE) 1009 { 1010 if (StreamHeader->DataUsed > StreamHeader->FrameExtent) 1011 { 1012 /* frame extend can never be smaller */ 1013 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 1014 } 1015 1016 /* is this stream change packet */ 1017 if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) 1018 { 1019 if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) 1020 { 1021 /* stream changed - must be send in a single packet */ 1022 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 1023 } 1024 1025 if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) 1026 { 1027 /* caller does not permit format changes */ 1028 ExRaiseStatus(STATUS_INVALID_PARAMETER); 1029 } 1030 1031 if (StreamHeader->FrameExtent) 1032 { 1033 /* allocate an mdl */ 1034 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); 1035 1036 if (!Mdl) 1037 { 1038 /* not enough memory */ 1039 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 1040 } 1041 1042 /* break out to probe for the irp */ 1043 //AllocateMdl = TRUE; 1044 break; 1045 } 1046 } 1047 } 1048 else 1049 { 1050 if (StreamHeader->DataUsed) 1051 { 1052 /* DataUsed must be zero for stream read operation */ 1053 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); 1054 } 1055 1056 if (StreamHeader->OptionsFlags) 1057 { 1058 /* no flags supported for reading */ 1059 ExRaiseStatus(STATUS_INVALID_PARAMETER); 1060 } 1061 } 1062 1063 /* move to next stream header */ 1064 Length -= StreamHeader->Size; 1065 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); 1066 }while(Length); 1067 1068 }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1069 { 1070 /* Exception, get the error code */ 1071 Status = _SEH2_GetExceptionCode(); 1072 }_SEH2_END; 1073 1074 /* now probe the allocated mdl's */ 1075 if (NT_SUCCESS(Status)) 1076 goto AllocMdl; 1077 else 1078 return Status; 1079 } 1080 1081 return STATUS_INVALID_BUFFER_SIZE; 1082 } 1083 1084 /* 1085 @implemented 1086 */ 1087 KSDDKAPI 1088 NTSTATUS 1089 NTAPI 1090 KsAllocateExtraData( 1091 IN PIRP Irp, 1092 IN ULONG ExtraSize, 1093 OUT PVOID* ExtraBuffer) 1094 { 1095 PIO_STACK_LOCATION IoStack; 1096 ULONG Count, Index; 1097 PUCHAR Buffer, BufferOrg; 1098 PKSSTREAM_HEADER Header; 1099 NTSTATUS Status = STATUS_SUCCESS; 1100 1101 /* get current irp stack */ 1102 IoStack = IoGetCurrentIrpStackLocation(Irp); 1103 1104 /* sanity check */ 1105 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER)); 1106 1107 /* get total length */ 1108 Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER); 1109 1110 /* allocate buffer */ 1111 Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize)); 1112 if (!Buffer) 1113 return STATUS_INSUFFICIENT_RESOURCES; 1114 1115 _SEH2_TRY 1116 { 1117 /* get input buffer */ 1118 Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 1119 for(Index = 0; Index < Count; Index++) 1120 { 1121 /* copy stream header */ 1122 RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER)); 1123 1124 /* move to next header */ 1125 Header++; 1126 /* increment output buffer offset */ 1127 Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize; 1128 } 1129 } 1130 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1131 { 1132 /* Exception, get the error code */ 1133 Status = _SEH2_GetExceptionCode(); 1134 } 1135 _SEH2_END; 1136 1137 if (!NT_SUCCESS(Status)) 1138 { 1139 /* free buffer on exception */ 1140 FreeItem(Buffer); 1141 return Status; 1142 } 1143 1144 /* store result */ 1145 *ExtraBuffer = BufferOrg; 1146 1147 /* done */ 1148 return STATUS_SUCCESS; 1149 } 1150 1151 /* 1152 @implemented 1153 */ 1154 KSDDKAPI 1155 VOID 1156 NTAPI 1157 KsNullDriverUnload( 1158 IN PDRIVER_OBJECT DriverObject) 1159 { 1160 } 1161 1162 /* 1163 @implemented 1164 */ 1165 KSDDKAPI 1166 NTSTATUS 1167 NTAPI 1168 KsDispatchInvalidDeviceRequest( 1169 IN PDEVICE_OBJECT DeviceObject, 1170 IN PIRP Irp) 1171 { 1172 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 1173 CompleteRequest(Irp, IO_NO_INCREMENT); 1174 1175 return STATUS_INVALID_DEVICE_REQUEST; 1176 } 1177 1178 /* 1179 @implemented 1180 */ 1181 KSDDKAPI 1182 NTSTATUS 1183 NTAPI 1184 KsDefaultDeviceIoCompletion( 1185 IN PDEVICE_OBJECT DeviceObject, 1186 IN PIRP Irp) 1187 { 1188 PIO_STACK_LOCATION IoStack; 1189 NTSTATUS Status; 1190 1191 /* get current irp stack */ 1192 IoStack = IoGetCurrentIrpStackLocation(Irp); 1193 1194 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY && 1195 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD && 1196 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_ENABLE_EVENT && 1197 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_DISABLE_EVENT) 1198 { 1199 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE) 1200 { 1201 /* fake success */ 1202 Status = STATUS_SUCCESS; 1203 } 1204 else 1205 { 1206 /* request unsupported */ 1207 Status = STATUS_INVALID_DEVICE_REQUEST; 1208 } 1209 } 1210 else 1211 { 1212 /* property / method / event not found */ 1213 Status = STATUS_PROPSET_NOT_FOUND; 1214 } 1215 1216 /* complete request */ 1217 Irp->IoStatus.Status = Status; 1218 CompleteRequest(Irp, IO_NO_INCREMENT); 1219 1220 1221 return Status; 1222 } 1223 1224 /* 1225 @implemented 1226 */ 1227 KSDDKAPI 1228 BOOLEAN 1229 NTAPI 1230 KsDispatchFastIoDeviceControlFailure( 1231 IN PFILE_OBJECT FileObject, 1232 IN BOOLEAN Wait, 1233 IN PVOID InputBuffer OPTIONAL, 1234 IN ULONG InputBufferLength, 1235 OUT PVOID OutputBuffer OPTIONAL, 1236 IN ULONG OutputBufferLength, 1237 IN ULONG IoControlCode, 1238 OUT PIO_STATUS_BLOCK IoStatus, 1239 IN PDEVICE_OBJECT DeviceObject) 1240 { 1241 return FALSE; 1242 } 1243 1244 /* 1245 @implemented 1246 */ 1247 KSDDKAPI 1248 BOOLEAN 1249 NTAPI 1250 KsDispatchFastReadFailure( 1251 IN PFILE_OBJECT FileObject, 1252 IN PLARGE_INTEGER FileOffset, 1253 IN ULONG Length, 1254 IN BOOLEAN Wait, 1255 IN ULONG LockKey, 1256 OUT PVOID Buffer, 1257 OUT PIO_STATUS_BLOCK IoStatus, 1258 IN PDEVICE_OBJECT DeviceObject) 1259 { 1260 return FALSE; 1261 } 1262 1263 1264 /* 1265 @implemented 1266 */ 1267 KSDDKAPI 1268 VOID 1269 NTAPI 1270 KsCancelIo( 1271 IN OUT PLIST_ENTRY QueueHead, 1272 IN PKSPIN_LOCK SpinLock) 1273 { 1274 PDRIVER_CANCEL OldDriverCancel; 1275 PIO_STACK_LOCATION IoStack; 1276 PLIST_ENTRY Entry; 1277 PLIST_ENTRY NextEntry; 1278 PIRP Irp; 1279 KIRQL OldLevel; 1280 1281 /* acquire spinlock */ 1282 KeAcquireSpinLock(SpinLock, &OldLevel); 1283 /* point to first entry */ 1284 Entry = QueueHead->Flink; 1285 /* loop all items */ 1286 while(Entry != QueueHead) 1287 { 1288 /* get irp offset */ 1289 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 1290 1291 /* get next entry */ 1292 NextEntry = Entry->Flink; 1293 1294 /* set cancelled bit */ 1295 Irp->Cancel = TRUE; 1296 1297 /* now set the cancel routine */ 1298 OldDriverCancel = IoSetCancelRoutine(Irp, NULL); 1299 if (OldDriverCancel) 1300 { 1301 /* this irp hasnt been yet used, so free to cancel */ 1302 KeReleaseSpinLock(SpinLock, OldLevel); 1303 1304 /* get current irp stack */ 1305 IoStack = IoGetCurrentIrpStackLocation(Irp); 1306 1307 /* acquire cancel spinlock */ 1308 IoAcquireCancelSpinLock(&Irp->CancelIrql); 1309 1310 /* call provided cancel routine */ 1311 OldDriverCancel(IoStack->DeviceObject, Irp); 1312 1313 /* re-acquire spinlock */ 1314 KeAcquireSpinLock(SpinLock, &OldLevel); 1315 } 1316 1317 /* move on to next entry */ 1318 Entry = NextEntry; 1319 } 1320 1321 /* the irp has already been canceled */ 1322 KeReleaseSpinLock(SpinLock, OldLevel); 1323 1324 } 1325 1326 /* 1327 @implemented 1328 */ 1329 KSDDKAPI 1330 VOID 1331 NTAPI 1332 KsReleaseIrpOnCancelableQueue( 1333 IN PIRP Irp, 1334 IN PDRIVER_CANCEL DriverCancel OPTIONAL) 1335 { 1336 PKSPIN_LOCK SpinLock; 1337 PDRIVER_CANCEL OldDriverCancel; 1338 PIO_STACK_LOCATION IoStack; 1339 KIRQL OldLevel; 1340 1341 /* check for required parameters */ 1342 if (!Irp) 1343 return; 1344 1345 if (!DriverCancel) 1346 { 1347 /* default to KsCancelRoutine */ 1348 DriverCancel = KsCancelRoutine; 1349 } 1350 1351 /* get current irp stack */ 1352 IoStack = IoGetCurrentIrpStackLocation(Irp); 1353 1354 /* get internal queue lock */ 1355 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); 1356 1357 /* acquire spinlock */ 1358 KeAcquireSpinLock(SpinLock, &OldLevel); 1359 1360 /* now set the cancel routine */ 1361 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); 1362 1363 if (Irp->Cancel && OldDriverCancel == NULL) 1364 { 1365 /* the irp has already been canceled */ 1366 KeReleaseSpinLock(SpinLock, OldLevel); 1367 1368 /* cancel routine requires that cancel spinlock is held */ 1369 IoAcquireCancelSpinLock(&Irp->CancelIrql); 1370 1371 /* cancel irp */ 1372 DriverCancel(IoStack->DeviceObject, Irp); 1373 } 1374 else 1375 { 1376 /* done */ 1377 KeReleaseSpinLock(SpinLock, OldLevel); 1378 } 1379 } 1380 1381 /* 1382 @implemented 1383 */ 1384 KSDDKAPI 1385 PIRP 1386 NTAPI 1387 KsRemoveIrpFromCancelableQueue( 1388 IN OUT PLIST_ENTRY QueueHead, 1389 IN PKSPIN_LOCK SpinLock, 1390 IN KSLIST_ENTRY_LOCATION ListLocation, 1391 IN KSIRP_REMOVAL_OPERATION RemovalOperation) 1392 { 1393 PIRP Irp; 1394 PLIST_ENTRY CurEntry; 1395 KIRQL OldIrql; 1396 1397 DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation); 1398 1399 /* check parameters */ 1400 if (!QueueHead || !SpinLock) 1401 return NULL; 1402 1403 /* check if parameter ListLocation is valid */ 1404 if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead) 1405 return NULL; 1406 1407 /* acquire list lock */ 1408 KeAcquireSpinLock(SpinLock, &OldIrql); 1409 1410 /* point to queue head */ 1411 CurEntry = QueueHead; 1412 1413 do 1414 { 1415 /* reset irp to null */ 1416 Irp = NULL; 1417 1418 /* iterate to next entry */ 1419 if (ListLocation == KsListEntryHead) 1420 CurEntry = CurEntry->Flink; 1421 else 1422 CurEntry = CurEntry->Blink; 1423 1424 /* is the end of list reached */ 1425 if (CurEntry == QueueHead) 1426 { 1427 /* reached end of list */ 1428 break; 1429 } 1430 1431 /* get irp offset */ 1432 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); 1433 1434 if (Irp->Cancel) 1435 { 1436 /* irp has been canceled */ 1437 break; 1438 } 1439 1440 if (Irp->CancelRoutine) 1441 { 1442 /* remove cancel routine */ 1443 Irp->CancelRoutine = NULL; 1444 1445 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) 1446 { 1447 /* remove irp from list */ 1448 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 1449 } 1450 1451 if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem) 1452 break; 1453 } 1454 1455 }while(TRUE); 1456 1457 /* release lock */ 1458 KeReleaseSpinLock(SpinLock, OldIrql); 1459 1460 if (!Irp || Irp->CancelRoutine == NULL) 1461 { 1462 /* either an irp has been acquired or nothing found */ 1463 return Irp; 1464 } 1465 1466 /* time to remove the canceled irp */ 1467 IoAcquireCancelSpinLock(&OldIrql); 1468 /* acquire list lock */ 1469 KeAcquireSpinLockAtDpcLevel(SpinLock); 1470 1471 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) 1472 { 1473 /* remove it */ 1474 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 1475 } 1476 1477 /* release list lock */ 1478 KeReleaseSpinLockFromDpcLevel(SpinLock); 1479 1480 /* release cancel spinlock */ 1481 IoReleaseCancelSpinLock(OldIrql); 1482 /* no non canceled irp has been found */ 1483 return NULL; 1484 } 1485 1486 /* 1487 @implemented 1488 */ 1489 KSDDKAPI 1490 NTSTATUS 1491 NTAPI 1492 KsMoveIrpsOnCancelableQueue( 1493 IN OUT PLIST_ENTRY SourceList, 1494 IN PKSPIN_LOCK SourceLock, 1495 IN OUT PLIST_ENTRY DestinationList, 1496 IN PKSPIN_LOCK DestinationLock OPTIONAL, 1497 IN KSLIST_ENTRY_LOCATION ListLocation, 1498 IN PFNKSIRPLISTCALLBACK ListCallback, 1499 IN PVOID Context) 1500 { 1501 KIRQL OldLevel; 1502 PLIST_ENTRY SrcEntry; 1503 PIRP Irp; 1504 NTSTATUS Status = STATUS_SUCCESS; 1505 1506 if (!DestinationLock) 1507 { 1508 /* no destination lock just acquire the source lock */ 1509 KeAcquireSpinLock(SourceLock, &OldLevel); 1510 } 1511 else 1512 { 1513 /* acquire cancel spinlock */ 1514 IoAcquireCancelSpinLock(&OldLevel); 1515 1516 /* now acquire source lock */ 1517 KeAcquireSpinLockAtDpcLevel(SourceLock); 1518 1519 /* now acquire destination lock */ 1520 KeAcquireSpinLockAtDpcLevel(DestinationLock); 1521 } 1522 1523 /* point to list head */ 1524 SrcEntry = SourceList; 1525 1526 /* now move all irps */ 1527 while(TRUE) 1528 { 1529 if (ListLocation == KsListEntryTail) 1530 { 1531 /* move queue downwards */ 1532 SrcEntry = SrcEntry->Flink; 1533 } 1534 else 1535 { 1536 /* move queue upwards */ 1537 SrcEntry = SrcEntry->Blink; 1538 } 1539 1540 if (SrcEntry == SourceList) 1541 { 1542 /* eof list reached */ 1543 break; 1544 } 1545 1546 /* get irp offset */ 1547 Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry); 1548 1549 /* now check if irp can be moved */ 1550 Status = ListCallback(Irp, Context); 1551 1552 /* check if irp can be moved */ 1553 if (Status == STATUS_SUCCESS) 1554 { 1555 /* remove irp from src list */ 1556 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 1557 1558 if (ListLocation == KsListEntryTail) 1559 { 1560 /* insert irp end of list */ 1561 InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry); 1562 } 1563 else 1564 { 1565 /* insert irp head of list */ 1566 InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry); 1567 } 1568 1569 /* do we need to update the irp lock */ 1570 if (DestinationLock) 1571 { 1572 /* update irp lock */ 1573 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock; 1574 } 1575 } 1576 else 1577 { 1578 if (Status != STATUS_NO_MATCH) 1579 { 1580 /* callback decided to stop enumeration */ 1581 break; 1582 } 1583 1584 /* reset return value */ 1585 Status = STATUS_SUCCESS; 1586 } 1587 } 1588 1589 if (!DestinationLock) 1590 { 1591 /* release source lock */ 1592 KeReleaseSpinLock(SourceLock, OldLevel); 1593 } 1594 else 1595 { 1596 /* now release destination lock */ 1597 KeReleaseSpinLockFromDpcLevel(DestinationLock); 1598 1599 /* now release source lock */ 1600 KeReleaseSpinLockFromDpcLevel(SourceLock); 1601 1602 1603 /* now release cancel spinlock */ 1604 IoReleaseCancelSpinLock(OldLevel); 1605 } 1606 1607 /* done */ 1608 return Status; 1609 } 1610 1611 /* 1612 @implemented 1613 */ 1614 KSDDKAPI 1615 VOID 1616 NTAPI 1617 KsRemoveSpecificIrpFromCancelableQueue( 1618 IN PIRP Irp) 1619 { 1620 PKSPIN_LOCK SpinLock; 1621 KIRQL OldLevel; 1622 1623 DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp); 1624 1625 /* get internal queue lock */ 1626 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); 1627 1628 /* acquire spinlock */ 1629 KeAcquireSpinLock(SpinLock, &OldLevel); 1630 1631 /* remove the irp from the list */ 1632 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 1633 1634 /* release spinlock */ 1635 KeReleaseSpinLock(SpinLock, OldLevel); 1636 } 1637 1638 1639 /* 1640 @implemented 1641 */ 1642 KSDDKAPI 1643 VOID 1644 NTAPI 1645 KsAddIrpToCancelableQueue( 1646 IN OUT PLIST_ENTRY QueueHead, 1647 IN PKSPIN_LOCK SpinLock, 1648 IN PIRP Irp, 1649 IN KSLIST_ENTRY_LOCATION ListLocation, 1650 IN PDRIVER_CANCEL DriverCancel OPTIONAL) 1651 { 1652 PDRIVER_CANCEL OldDriverCancel; 1653 PIO_STACK_LOCATION IoStack; 1654 KIRQL OldLevel; 1655 1656 /* check for required parameters */ 1657 if (!QueueHead || !SpinLock || !Irp) 1658 return; 1659 1660 /* get current irp stack */ 1661 IoStack = IoGetCurrentIrpStackLocation(Irp); 1662 1663 DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); 1664 1665 // HACK for ms portcls 1666 if (IoStack->MajorFunction == IRP_MJ_CREATE) 1667 { 1668 // complete the request 1669 DPRINT1("MS HACK\n"); 1670 Irp->IoStatus.Status = STATUS_SUCCESS; 1671 CompleteRequest(Irp, IO_NO_INCREMENT); 1672 1673 return; 1674 } 1675 1676 1677 if (!DriverCancel) 1678 { 1679 /* default to KsCancelRoutine */ 1680 DriverCancel = KsCancelRoutine; 1681 } 1682 1683 1684 /* acquire spinlock */ 1685 KeAcquireSpinLock(SpinLock, &OldLevel); 1686 1687 if (ListLocation == KsListEntryTail) 1688 { 1689 /* insert irp to tail of list */ 1690 InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry); 1691 } 1692 else 1693 { 1694 /* insert irp to head of list */ 1695 InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry); 1696 } 1697 1698 /* store internal queue lock */ 1699 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock; 1700 1701 /* now set the cancel routine */ 1702 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); 1703 1704 if (Irp->Cancel && OldDriverCancel == NULL) 1705 { 1706 /* the irp has already been canceled */ 1707 KeReleaseSpinLock(SpinLock, OldLevel); 1708 1709 /* cancel routine requires that cancel spinlock is held */ 1710 IoAcquireCancelSpinLock(&Irp->CancelIrql); 1711 1712 /* cancel irp */ 1713 DriverCancel(IoStack->DeviceObject, Irp); 1714 } 1715 else 1716 { 1717 /* done */ 1718 KeReleaseSpinLock(SpinLock, OldLevel); 1719 } 1720 } 1721 1722 /* 1723 @implemented 1724 */ 1725 KSDDKAPI 1726 VOID 1727 NTAPI 1728 KsCancelRoutine( 1729 IN PDEVICE_OBJECT DeviceObject, 1730 IN PIRP Irp) 1731 { 1732 PKSPIN_LOCK SpinLock; 1733 1734 /* get internal queue lock */ 1735 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp); 1736 1737 /* acquire spinlock */ 1738 KeAcquireSpinLockAtDpcLevel(SpinLock); 1739 1740 /* sanity check */ 1741 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 1742 1743 /* release cancel spinlock */ 1744 IoReleaseCancelSpinLock(Irp->CancelIrql); 1745 1746 /* remove the irp from the list */ 1747 RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 1748 1749 /* release spinlock */ 1750 KeReleaseSpinLock(SpinLock, Irp->CancelIrql); 1751 1752 /* has the irp already been canceled */ 1753 if (Irp->IoStatus.Status != STATUS_CANCELLED) 1754 { 1755 /* let's complete it */ 1756 Irp->IoStatus.Status = STATUS_CANCELLED; 1757 CompleteRequest(Irp, IO_NO_INCREMENT); 1758 } 1759 } 1760 1761 NTSTATUS 1762 FindMatchingCreateItem( 1763 PLIST_ENTRY ListHead, 1764 PUNICODE_STRING String, 1765 OUT PCREATE_ITEM_ENTRY *OutCreateItem) 1766 { 1767 PLIST_ENTRY Entry; 1768 PCREATE_ITEM_ENTRY CreateItemEntry; 1769 UNICODE_STRING RefString; 1770 LPWSTR pStr; 1771 ULONG Count; 1772 1773 /* Copy the input string */ 1774 RefString = *String; 1775 1776 /* Check if the string starts with a backslash */ 1777 if (String->Buffer[0] == L'\\') 1778 { 1779 /* Skip backslash */ 1780 RefString.Buffer++; 1781 RefString.Length -= sizeof(WCHAR); 1782 } 1783 else 1784 { 1785 /* get terminator */ 1786 pStr = String->Buffer; 1787 Count = String->Length / sizeof(WCHAR); 1788 while ((Count > 0) && (*pStr != L'\\')) 1789 { 1790 pStr++; 1791 Count--; 1792 } 1793 1794 /* sanity check */ 1795 ASSERT(Count != 0); 1796 1797 // request is for pin / node / allocator 1798 RefString.Length = (USHORT)((PCHAR)pStr - (PCHAR)String->Buffer); 1799 } 1800 1801 /* point to first entry */ 1802 Entry = ListHead->Flink; 1803 1804 /* loop all device items */ 1805 while (Entry != ListHead) 1806 { 1807 /* get create item entry */ 1808 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, 1809 CREATE_ITEM_ENTRY, 1810 Entry); 1811 1812 ASSERT(CreateItemEntry->CreateItem); 1813 1814 if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD) 1815 { 1816 /* create item is default */ 1817 *OutCreateItem = CreateItemEntry; 1818 return STATUS_SUCCESS; 1819 } 1820 1821 if (!CreateItemEntry->CreateItem->Create) 1822 { 1823 /* skip free create item */ 1824 Entry = Entry->Flink; 1825 continue; 1826 } 1827 1828 DPRINT("CreateItem %S Length %u Request %wZ %u\n", 1829 CreateItemEntry->CreateItem->ObjectClass.Buffer, 1830 CreateItemEntry->CreateItem->ObjectClass.Length, 1831 &RefString, 1832 RefString.Length); 1833 1834 if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length) 1835 { 1836 /* create item doesnt match in length */ 1837 Entry = Entry->Flink; 1838 continue; 1839 } 1840 1841 /* now check if the object class is the same */ 1842 if (!RtlCompareUnicodeString(&CreateItemEntry->CreateItem->ObjectClass, 1843 &RefString, 1844 TRUE)) 1845 { 1846 /* found matching create item */ 1847 *OutCreateItem = CreateItemEntry; 1848 return STATUS_SUCCESS; 1849 } 1850 /* iterate to next */ 1851 Entry = Entry->Flink; 1852 } 1853 1854 return STATUS_NOT_FOUND; 1855 } 1856 1857 NTSTATUS 1858 NTAPI 1859 KspCreate( 1860 IN PDEVICE_OBJECT DeviceObject, 1861 IN PIRP Irp) 1862 { 1863 PCREATE_ITEM_ENTRY CreateItemEntry; 1864 PIO_STACK_LOCATION IoStack; 1865 PDEVICE_EXTENSION DeviceExtension; 1866 PKSIDEVICE_HEADER DeviceHeader; 1867 PKSIOBJECT_HEADER ObjectHeader; 1868 NTSTATUS Status; 1869 1870 DPRINT("KS / CREATE\n"); 1871 1872 /* get current stack location */ 1873 IoStack = IoGetCurrentIrpStackLocation(Irp); 1874 /* get device extension */ 1875 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 1876 /* get device header */ 1877 DeviceHeader = DeviceExtension->DeviceHeader; 1878 1879 1880 if (IoStack->FileObject->FileName.Buffer == NULL) 1881 { 1882 /* FIXME Pnp-Issue */ 1883 DPRINT("Using reference string hack\n"); 1884 Irp->IoStatus.Information = 0; 1885 /* set return status */ 1886 Irp->IoStatus.Status = STATUS_SUCCESS; 1887 CompleteRequest(Irp, IO_NO_INCREMENT); 1888 return STATUS_SUCCESS; 1889 } 1890 1891 if (IoStack->FileObject->RelatedFileObject != NULL) 1892 { 1893 /* request is to instantiate a pin / node / clock / allocator */ 1894 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2; 1895 1896 /* sanity check */ 1897 ASSERT(ObjectHeader); 1898 1899 /* find a matching a create item */ 1900 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, 1901 &IoStack->FileObject->FileName, 1902 &CreateItemEntry); 1903 } 1904 else 1905 { 1906 /* request to create a filter */ 1907 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, 1908 &IoStack->FileObject->FileName, 1909 &CreateItemEntry); 1910 } 1911 1912 if (NT_SUCCESS(Status)) 1913 { 1914 /* set object create item */ 1915 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem; 1916 1917 /* call create function */ 1918 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp); 1919 1920 if (NT_SUCCESS(Status)) 1921 { 1922 /* increment create item reference count */ 1923 InterlockedIncrement(&CreateItemEntry->ReferenceCount); 1924 } 1925 return Status; 1926 } 1927 1928 Irp->IoStatus.Information = 0; 1929 /* set return status */ 1930 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 1931 CompleteRequest(Irp, IO_NO_INCREMENT); 1932 return STATUS_UNSUCCESSFUL; 1933 } 1934 1935 NTSTATUS 1936 NTAPI 1937 KspDispatchIrp( 1938 IN PDEVICE_OBJECT DeviceObject, 1939 IN PIRP Irp) 1940 { 1941 PIO_STACK_LOCATION IoStack; 1942 //PDEVICE_EXTENSION DeviceExtension; 1943 PKSIOBJECT_HEADER ObjectHeader; 1944 //PKSIDEVICE_HEADER DeviceHeader; 1945 PDRIVER_DISPATCH Dispatch; 1946 NTSTATUS Status; 1947 1948 /* get current stack location */ 1949 IoStack = IoGetCurrentIrpStackLocation(Irp); 1950 1951 /* get device extension */ 1952 //DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 1953 /* get device header */ 1954 //DeviceHeader = DeviceExtension->DeviceHeader; 1955 1956 ASSERT(IoStack->FileObject); 1957 1958 /* get object header */ 1959 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2; 1960 1961 if (!ObjectHeader) 1962 { 1963 /* FIXME Pnp-Issue*/ 1964 Irp->IoStatus.Status = STATUS_SUCCESS; 1965 Irp->IoStatus.Information = 0; 1966 /* complete and forget */ 1967 CompleteRequest(Irp, IO_NO_INCREMENT); 1968 return STATUS_SUCCESS; 1969 } 1970 1971 /* sanity check */ 1972 ASSERT(ObjectHeader); 1973 /* store create item */ 1974 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem; 1975 1976 /* retrieve matching dispatch function */ 1977 switch(IoStack->MajorFunction) 1978 { 1979 case IRP_MJ_CLOSE: 1980 Dispatch = ObjectHeader->DispatchTable.Close; 1981 break; 1982 case IRP_MJ_DEVICE_CONTROL: 1983 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl; 1984 break; 1985 case IRP_MJ_READ: 1986 Dispatch = ObjectHeader->DispatchTable.Read; 1987 break; 1988 case IRP_MJ_WRITE: 1989 Dispatch = ObjectHeader->DispatchTable.Write; 1990 break; 1991 case IRP_MJ_FLUSH_BUFFERS : 1992 Dispatch = ObjectHeader->DispatchTable.Flush; 1993 break; 1994 case IRP_MJ_QUERY_SECURITY: 1995 Dispatch = ObjectHeader->DispatchTable.QuerySecurity; 1996 break; 1997 case IRP_MJ_SET_SECURITY: 1998 Dispatch = ObjectHeader->DispatchTable.SetSecurity; 1999 break; 2000 case IRP_MJ_PNP: 2001 Dispatch = KsDefaultDispatchPnp; 2002 break; 2003 default: 2004 Dispatch = NULL; 2005 } 2006 2007 /* is the request supported */ 2008 if (Dispatch) 2009 { 2010 /* now call the dispatch function */ 2011 Status = Dispatch(DeviceObject, Irp); 2012 } 2013 else 2014 { 2015 /* not supported request */ 2016 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 2017 } 2018 2019 /* done */ 2020 return Status; 2021 } 2022 2023 /* 2024 @implemented 2025 */ 2026 KSDDKAPI 2027 NTSTATUS 2028 NTAPI 2029 KsSetMajorFunctionHandler( 2030 IN PDRIVER_OBJECT DriverObject, 2031 IN ULONG MajorFunction) 2032 { 2033 DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction); 2034 2035 switch ( MajorFunction ) 2036 { 2037 case IRP_MJ_CREATE: 2038 DriverObject->MajorFunction[MajorFunction] = KspCreate; 2039 break; 2040 case IRP_MJ_DEVICE_CONTROL: 2041 case IRP_MJ_CLOSE: 2042 case IRP_MJ_READ: 2043 case IRP_MJ_WRITE: 2044 case IRP_MJ_FLUSH_BUFFERS : 2045 case IRP_MJ_QUERY_SECURITY: 2046 case IRP_MJ_SET_SECURITY: 2047 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp; 2048 break; 2049 default: 2050 DPRINT1("NotSupported %x\n", MajorFunction); 2051 return STATUS_INVALID_PARAMETER; 2052 }; 2053 2054 return STATUS_SUCCESS; 2055 } 2056 2057 /* 2058 @implemented 2059 */ 2060 KSDDKAPI 2061 NTSTATUS 2062 NTAPI 2063 KsDispatchIrp( 2064 IN PDEVICE_OBJECT DeviceObject, 2065 IN PIRP Irp) 2066 { 2067 PIO_STACK_LOCATION IoStack; 2068 PKSIDEVICE_HEADER DeviceHeader; 2069 PDEVICE_EXTENSION DeviceExtension; 2070 2071 DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp); 2072 2073 /* get device extension */ 2074 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 2075 2076 /* get device header */ 2077 DeviceHeader = DeviceExtension->DeviceHeader; 2078 2079 2080 /* get current irp stack */ 2081 IoStack = IoGetCurrentIrpStackLocation(Irp); 2082 2083 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL) 2084 { 2085 if (IoStack->MajorFunction == IRP_MJ_CREATE) 2086 { 2087 /* check internal type */ 2088 if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ 2089 { 2090 /* AVStream client */ 2091 return IKsDevice_Create(DeviceObject, Irp); 2092 } 2093 else 2094 { 2095 /* external client (portcls) */ 2096 return KspCreate(DeviceObject, Irp); 2097 } 2098 } 2099 2100 switch (IoStack->MajorFunction) 2101 { 2102 case IRP_MJ_CLOSE: 2103 case IRP_MJ_READ: 2104 case IRP_MJ_WRITE: 2105 case IRP_MJ_FLUSH_BUFFERS: 2106 case IRP_MJ_QUERY_SECURITY: 2107 case IRP_MJ_SET_SECURITY: 2108 case IRP_MJ_PNP: 2109 case IRP_MJ_DEVICE_CONTROL: 2110 return KspDispatchIrp(DeviceObject, Irp); 2111 default: 2112 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 2113 } 2114 } 2115 2116 /* dispatch power */ 2117 if (IoStack->MajorFunction == IRP_MJ_POWER) 2118 { 2119 /* check internal type */ 2120 if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ 2121 { 2122 /* AVStream client */ 2123 return IKsDevice_Power(DeviceObject, Irp); 2124 } 2125 else 2126 { 2127 /* external client (portcls) */ 2128 return KsDefaultDispatchPower(DeviceObject, Irp); 2129 } 2130 } 2131 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */ 2132 { 2133 /* check internal type */ 2134 if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */ 2135 { 2136 /* AVStream client */ 2137 return IKsDevice_Pnp(DeviceObject, Irp); 2138 } 2139 else 2140 { 2141 /* external client (portcls) */ 2142 return KsDefaultDispatchPnp(DeviceObject, Irp); 2143 } 2144 } 2145 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL) 2146 { 2147 /* forward irp */ 2148 return KsDefaultForwardIrp(DeviceObject, Irp); 2149 } 2150 else 2151 { 2152 /* not supported */ 2153 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); 2154 } 2155 } 2156 2157 /* 2158 @unimplemented 2159 */ 2160 KSDDKAPI 2161 ULONG 2162 NTAPI 2163 KsGetNodeIdFromIrp( 2164 IN PIRP Irp) 2165 { 2166 UNIMPLEMENTED; 2167 return KSFILTER_NODE; 2168 } 2169 2170