1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/ksfilter/ks/api.c 5 * PURPOSE: KS API functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; 15 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 16 17 /* 18 @implemented 19 */ 20 KSDDKAPI 21 NTSTATUS 22 NTAPI 23 KsAcquireResetValue( 24 IN PIRP Irp, 25 OUT KSRESET* ResetValue) 26 { 27 PIO_STACK_LOCATION IoStack; 28 KSRESET* Value; 29 NTSTATUS Status = STATUS_SUCCESS; 30 31 /* get current irp stack */ 32 IoStack = IoGetCurrentIrpStackLocation(Irp); 33 34 /* check if there is reset value provided */ 35 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSRESET)) 36 return STATUS_INVALID_PARAMETER; 37 38 if (Irp->RequestorMode == UserMode) 39 { 40 /* need to probe the buffer */ 41 _SEH2_TRY 42 { 43 ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSRESET), sizeof(UCHAR)); 44 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 45 *ResetValue = *Value; 46 } 47 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 48 { 49 /* Exception, get the error code */ 50 Status = _SEH2_GetExceptionCode(); 51 } 52 _SEH2_END; 53 } 54 else 55 { 56 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 57 *ResetValue = *Value; 58 } 59 60 return Status; 61 } 62 63 /* 64 @implemented 65 */ 66 KSDDKAPI 67 VOID 68 NTAPI 69 KsAcquireDeviceSecurityLock( 70 IN KSDEVICE_HEADER DevHeader, 71 IN BOOLEAN Exclusive) 72 { 73 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader; 74 75 KeEnterCriticalRegion(); 76 77 if (Exclusive) 78 { 79 ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE); 80 } 81 else 82 { 83 ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE); 84 } 85 } 86 87 /* 88 @implemented 89 */ 90 KSDDKAPI 91 VOID 92 NTAPI 93 KsReleaseDeviceSecurityLock( 94 IN KSDEVICE_HEADER DevHeader) 95 { 96 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader; 97 98 DPRINT("KsReleaseDevice\n"); 99 100 ExReleaseResourceLite(&Header->SecurityLock); 101 KeLeaveCriticalRegion(); 102 } 103 104 /* 105 @implemented 106 */ 107 KSDDKAPI 108 NTSTATUS 109 NTAPI 110 KsDefaultDispatchPnp( 111 IN PDEVICE_OBJECT DeviceObject, 112 IN PIRP Irp) 113 { 114 PDEVICE_EXTENSION DeviceExtension; 115 PKSIDEVICE_HEADER DeviceHeader; 116 PIO_STACK_LOCATION IoStack; 117 PDEVICE_OBJECT PnpDeviceObject; 118 NTSTATUS Status; 119 ULONG MinorFunction; 120 121 /* get current irp stack */ 122 IoStack = IoGetCurrentIrpStackLocation(Irp); 123 124 /* caller wants to add the target device */ 125 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 126 127 /* get device header */ 128 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 129 130 /* backup PnpBaseObject */ 131 PnpDeviceObject = DeviceHeader->PnpDeviceObject; 132 133 134 /* backup minor function code */ 135 MinorFunction = IoStack->MinorFunction; 136 137 if(MinorFunction == IRP_MN_REMOVE_DEVICE) 138 { 139 /* remove the device */ 140 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader); 141 } 142 143 /* skip current irp stack */ 144 IoSkipCurrentIrpStackLocation(Irp); 145 146 /* call attached pnp device object */ 147 Status = IoCallDriver(PnpDeviceObject, Irp); 148 149 if (MinorFunction == IRP_MN_REMOVE_DEVICE) 150 { 151 /* time is over */ 152 IoDetachDevice(PnpDeviceObject); 153 /* delete device */ 154 IoDeleteDevice(DeviceObject); 155 } 156 /* done */ 157 return Status; 158 } 159 160 /* 161 @implemented 162 */ 163 KSDDKAPI 164 NTSTATUS 165 NTAPI 166 KsDefaultDispatchPower( 167 IN PDEVICE_OBJECT DeviceObject, 168 IN PIRP Irp) 169 { 170 PDEVICE_EXTENSION DeviceExtension; 171 PKSIDEVICE_HEADER DeviceHeader; 172 PKSIOBJECT_HEADER ObjectHeader; 173 //PIO_STACK_LOCATION IoStack; 174 PLIST_ENTRY ListEntry; 175 NTSTATUS Status; 176 177 /* get current irp stack */ 178 //IoStack = IoGetCurrentIrpStackLocation(Irp); 179 180 /* caller wants to add the target device */ 181 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 182 183 /* get device header */ 184 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 185 186 /* FIXME locks */ 187 188 /* loop our power dispatch list and call registered notification functions */ 189 ListEntry = DeviceHeader->PowerDispatchList.Flink; 190 /* let's go */ 191 while(ListEntry != &DeviceHeader->PowerDispatchList) 192 { 193 /* get object header */ 194 ObjectHeader = (PKSIOBJECT_HEADER)CONTAINING_RECORD(ListEntry, KSIOBJECT_HEADER, PowerDispatchEntry); 195 196 /* does it have still a cb */ 197 if (ObjectHeader->PowerDispatch) 198 { 199 /* call the power cb */ 200 Status = ObjectHeader->PowerDispatch(ObjectHeader->PowerContext, Irp); 201 ASSERT(NT_SUCCESS(Status)); 202 } 203 204 /* iterate to next entry */ 205 ListEntry = ListEntry->Flink; 206 } 207 208 /* start next power irp */ 209 PoStartNextPowerIrp(Irp); 210 211 /* skip current irp stack location */ 212 IoSkipCurrentIrpStackLocation(Irp); 213 214 /* let's roll */ 215 Status = PoCallDriver(DeviceHeader->PnpDeviceObject, Irp); 216 217 /* done */ 218 return Status; 219 } 220 221 /* 222 @implemented 223 */ 224 KSDDKAPI 225 NTSTATUS 226 NTAPI 227 KsDefaultForwardIrp( 228 IN PDEVICE_OBJECT DeviceObject, 229 IN PIRP Irp) 230 { 231 PDEVICE_EXTENSION DeviceExtension; 232 PKSIDEVICE_HEADER DeviceHeader; 233 //PIO_STACK_LOCATION IoStack; 234 NTSTATUS Status; 235 236 /* get current irp stack */ 237 //IoStack = IoGetCurrentIrpStackLocation(Irp); 238 239 /* caller wants to add the target device */ 240 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 241 242 /* get device header */ 243 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 244 245 /* forward the request to the PDO */ 246 Status = IoCallDriver(DeviceHeader->PnpDeviceObject, Irp); 247 248 return Status; 249 } 250 251 /* 252 @implemented 253 */ 254 KSDDKAPI 255 VOID 256 NTAPI 257 KsSetDevicePnpAndBaseObject( 258 IN KSDEVICE_HEADER Header, 259 IN PDEVICE_OBJECT PnpDeviceObject, 260 IN PDEVICE_OBJECT BaseDevice) 261 { 262 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header; 263 264 DeviceHeader->PnpDeviceObject = PnpDeviceObject; 265 DeviceHeader->BaseDevice = BaseDevice; 266 } 267 268 /* 269 @implemented 270 */ 271 KSDDKAPI 272 PDEVICE_OBJECT 273 NTAPI 274 KsQueryDevicePnpObject( 275 IN KSDEVICE_HEADER Header) 276 { 277 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header; 278 279 /* return PnpDeviceObject */ 280 return DeviceHeader->PnpDeviceObject; 281 282 } 283 284 /* 285 @implemented 286 */ 287 KSDDKAPI 288 ACCESS_MASK 289 NTAPI 290 KsQueryObjectAccessMask( 291 IN KSOBJECT_HEADER Header) 292 { 293 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header; 294 295 /* return access mask */ 296 return ObjectHeader->AccessMask; 297 298 } 299 300 /* 301 @unimplemented 302 */ 303 KSDDKAPI 304 VOID 305 NTAPI 306 KsRecalculateStackDepth( 307 IN KSDEVICE_HEADER Header, 308 IN BOOLEAN ReuseStackLocation) 309 { 310 UNIMPLEMENTED; 311 } 312 313 314 /* 315 @implemented 316 */ 317 KSDDKAPI 318 VOID 319 NTAPI 320 KsSetTargetState( 321 IN KSOBJECT_HEADER Header, 322 IN KSTARGET_STATE TargetState) 323 { 324 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header; 325 326 /* set target state */ 327 DeviceHeader->TargetState = TargetState; 328 } 329 330 /* 331 @implemented 332 */ 333 KSDDKAPI 334 VOID 335 NTAPI 336 KsSetTargetDeviceObject( 337 IN KSOBJECT_HEADER Header, 338 IN PDEVICE_OBJECT TargetDevice OPTIONAL) 339 { 340 PDEVICE_EXTENSION DeviceExtension; 341 PKSIDEVICE_HEADER DeviceHeader; 342 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header; 343 344 if(ObjectHeader->TargetDevice) 345 { 346 /* there is already a target device set */ 347 if (!TargetDevice) 348 { 349 /* caller wants to remove the target device */ 350 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension; 351 352 /* get device header */ 353 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 354 355 /* acquire lock */ 356 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE); 357 358 /* remove entry */ 359 RemoveEntryList(&ObjectHeader->TargetDeviceListEntry); 360 361 /* remove device pointer */ 362 ObjectHeader->TargetDevice = NULL; 363 364 /* release lock */ 365 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader); 366 } 367 } 368 else 369 { 370 /* no target device yet set */ 371 if (TargetDevice) 372 { 373 /* caller wants to add the target device */ 374 DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension; 375 376 /* get device header */ 377 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 378 379 /* acquire lock */ 380 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE); 381 382 /* insert list entry */ 383 InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry); 384 385 /* store target device */ 386 ObjectHeader->TargetDevice = TargetDevice; 387 388 /* release lock */ 389 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader); 390 } 391 } 392 393 } 394 395 /* 396 @implemented 397 */ 398 KSDDKAPI 399 VOID 400 NTAPI 401 KsSetPowerDispatch( 402 IN KSOBJECT_HEADER Header, 403 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL, 404 IN PVOID PowerContext OPTIONAL) 405 { 406 PDEVICE_EXTENSION DeviceExtension; 407 PKSIDEVICE_HEADER DeviceHeader; 408 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header; 409 410 /* caller wants to add the target device */ 411 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension; 412 413 /* get device header */ 414 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader; 415 416 /* acquire lock */ 417 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE); 418 419 if (PowerDispatch) 420 { 421 /* add power dispatch entry */ 422 InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry); 423 424 /* store function and context */ 425 ObjectHeader->PowerDispatch = PowerDispatch; 426 ObjectHeader->PowerContext = PowerContext; 427 } 428 else 429 { 430 /* remove power dispatch entry */ 431 RemoveEntryList(&ObjectHeader->PowerDispatchEntry); 432 433 /* store function and context */ 434 ObjectHeader->PowerDispatch = NULL; 435 ObjectHeader->PowerContext = NULL; 436 437 } 438 439 /* release lock */ 440 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader); 441 } 442 443 444 /* 445 @implemented 446 */ 447 KSDDKAPI 448 PKSOBJECT_CREATE_ITEM 449 NTAPI 450 KsQueryObjectCreateItem( 451 IN KSOBJECT_HEADER Header) 452 { 453 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header; 454 return ObjectHeader->OriginalCreateItem; 455 } 456 457 NTSTATUS 458 KspAddCreateItemToList( 459 OUT PLIST_ENTRY ListHead, 460 IN ULONG ItemsCount, 461 IN PKSOBJECT_CREATE_ITEM ItemsList) 462 { 463 ULONG Index; 464 PCREATE_ITEM_ENTRY Entry; 465 466 /* add the items */ 467 for(Index = 0; Index < ItemsCount; Index++) 468 { 469 /* allocate item */ 470 Entry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY)); 471 if (!Entry) 472 { 473 /* no memory */ 474 return STATUS_INSUFFICIENT_RESOURCES; 475 } 476 477 /* initialize entry */ 478 InitializeListHead(&Entry->ObjectItemList); 479 Entry->CreateItem = &ItemsList[Index]; 480 Entry->ReferenceCount = 0; 481 Entry->ItemFreeCallback = NULL; 482 483 InsertTailList(ListHead, &Entry->Entry); 484 } 485 return STATUS_SUCCESS; 486 } 487 488 VOID 489 KspFreeCreateItems( 490 PLIST_ENTRY ListHead) 491 { 492 PCREATE_ITEM_ENTRY Entry; 493 494 while(!IsListEmpty(ListHead)) 495 { 496 /* remove create item from list */ 497 Entry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(RemoveHeadList(ListHead), CREATE_ITEM_ENTRY, Entry); 498 499 /* caller shouldnt have any references */ 500 //ASSERT(Entry->ReferenceCount == 0); 501 //ASSERT(IsListEmpty(&Entry->ObjectItemList)); 502 503 /* does the creator wish notification */ 504 if (Entry->ItemFreeCallback) 505 { 506 /* notify creator */ 507 Entry->ItemFreeCallback(Entry->CreateItem); 508 } 509 510 /* free create item entry */ 511 FreeItem(Entry); 512 } 513 514 } 515 516 /* 517 @implemented 518 */ 519 KSDDKAPI 520 NTSTATUS 521 NTAPI 522 KsAllocateDeviceHeader( 523 OUT KSDEVICE_HEADER* OutHeader, 524 IN ULONG ItemsCount, 525 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL) 526 { 527 NTSTATUS Status = STATUS_SUCCESS; 528 PKSIDEVICE_HEADER Header; 529 530 if (!OutHeader) 531 return STATUS_INVALID_PARAMETER; 532 533 /* allocate a device header */ 534 Header = AllocateItem(PagedPool, sizeof(KSIDEVICE_HEADER)); 535 536 /* check for success */ 537 if (!Header) 538 return STATUS_INSUFFICIENT_RESOURCES; 539 540 /* clear all memory */ 541 RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER)); 542 543 /* initialize device mutex */ 544 KeInitializeMutex(&Header->DeviceMutex, 0); 545 546 /* initialize target device list */ 547 InitializeListHead(&Header->TargetDeviceList); 548 /* initialize power dispatch list */ 549 InitializeListHead(&Header->PowerDispatchList); 550 /* initialize object bag lists */ 551 InitializeListHead(&Header->ObjectBags); 552 553 /* initialize create item list */ 554 InitializeListHead(&Header->ItemList); 555 556 /* initialize basic header */ 557 Header->BasicHeader.Type = KsObjectTypeDevice; 558 Header->BasicHeader.KsDevice = &Header->KsDevice; 559 Header->BasicHeader.Parent.KsDevice = &Header->KsDevice; 560 561 /* are there any create items provided */ 562 if (ItemsCount && ItemsList) 563 { 564 Status = KspAddCreateItemToList(&Header->ItemList, ItemsCount, ItemsList); 565 566 if (NT_SUCCESS(Status)) 567 { 568 /* store item count */ 569 Header->ItemListCount = ItemsCount; 570 } 571 else 572 { 573 /* release create items */ 574 KspFreeCreateItems(&Header->ItemList); 575 } 576 } 577 578 /* store result */ 579 *OutHeader = Header; 580 581 return Status; 582 } 583 584 /* 585 @implemented 586 */ 587 KSDDKAPI 588 VOID 589 NTAPI 590 KsFreeDeviceHeader( 591 IN KSDEVICE_HEADER DevHeader) 592 { 593 PKSIDEVICE_HEADER Header; 594 595 Header = (PKSIDEVICE_HEADER)DevHeader; 596 597 if (!DevHeader) 598 return; 599 600 KspFreeCreateItems(&Header->ItemList); 601 FreeItem(Header); 602 } 603 604 /* 605 @implemented 606 */ 607 KSDDKAPI 608 NTSTATUS 609 NTAPI 610 KsAllocateObjectHeader( 611 OUT KSOBJECT_HEADER *Header, 612 IN ULONG ItemsCount, 613 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL, 614 IN PIRP Irp, 615 IN KSDISPATCH_TABLE* Table) 616 { 617 PIO_STACK_LOCATION IoStack; 618 //PDEVICE_EXTENSION DeviceExtension; 619 //PKSIDEVICE_HEADER DeviceHeader; 620 PKSIOBJECT_HEADER ObjectHeader; 621 //PKSOBJECT_CREATE_ITEM CreateItem; 622 NTSTATUS Status; 623 624 if (!Header) 625 return STATUS_INVALID_PARAMETER_1; 626 627 if (!Irp) 628 return STATUS_INVALID_PARAMETER_4; 629 630 if (!Table) 631 return STATUS_INVALID_PARAMETER_5; 632 633 /* get current stack location */ 634 IoStack = IoGetCurrentIrpStackLocation(Irp); 635 /* get device extension */ 636 //DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension; 637 /* get device header */ 638 //DeviceHeader = DeviceExtension->DeviceHeader; 639 640 /* sanity check */ 641 ASSERT(IoStack->FileObject); 642 /* check for an file object */ 643 644 /* allocate the object header */ 645 ObjectHeader = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_HEADER)); 646 if (!ObjectHeader) 647 return STATUS_INSUFFICIENT_RESOURCES; 648 649 /* initialize object header */ 650 RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER)); 651 652 /* initialize create item list */ 653 InitializeListHead(&ObjectHeader->ItemList); 654 655 /* get create item */ 656 //CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); 657 658 /* do we have a name */ 659 if (IoStack->FileObject->FileName.Buffer) 660 { 661 /* copy object class */ 662 ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength; 663 ObjectHeader->ObjectClass.Buffer = AllocateItem(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength); 664 if (!ObjectHeader->ObjectClass.Buffer) 665 { 666 FreeItem(ObjectHeader); 667 return STATUS_INSUFFICIENT_RESOURCES; 668 } 669 RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName); 670 } 671 672 /* copy dispatch table */ 673 RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE)); 674 675 /* store create items */ 676 if (ItemsCount && ItemsList) 677 { 678 Status = KspAddCreateItemToList(&ObjectHeader->ItemList, ItemsCount, ItemsList); 679 680 if (NT_SUCCESS(Status)) 681 { 682 /* store item count */ 683 ObjectHeader->ItemListCount = ItemsCount; 684 } 685 else 686 { 687 /* destroy header*/ 688 KsFreeObjectHeader(ObjectHeader); 689 return Status; 690 } 691 } 692 /* store the object in the file object */ 693 IoStack->FileObject->FsContext2 = ObjectHeader; 694 695 /* store parent device */ 696 ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject); 697 698 /* store originating create item */ 699 ObjectHeader->OriginalCreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); 700 701 /* FIXME store access mask see KsQueryObjectAccessMask */ 702 ObjectHeader->AccessMask = IoStack->Parameters.Create.SecurityContext->DesiredAccess; 703 704 705 /* store result */ 706 *Header = ObjectHeader; 707 708 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader); 709 710 return STATUS_SUCCESS; 711 712 } 713 714 /* 715 @implemented 716 */ 717 KSDDKAPI 718 VOID 719 NTAPI 720 KsFreeObjectHeader( 721 IN PVOID Header) 722 { 723 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header; 724 725 DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header, &ObjectHeader->ObjectClass); 726 727 if (ObjectHeader->ObjectClass.Buffer) 728 { 729 /* release object class buffer */ 730 FreeItem(ObjectHeader->ObjectClass.Buffer); 731 } 732 733 if (ObjectHeader->Unknown) 734 { 735 /* release associated object */ 736 ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown); 737 } 738 739 /* free create items */ 740 KspFreeCreateItems(&ObjectHeader->ItemList); 741 742 /* free object header */ 743 FreeItem(ObjectHeader); 744 745 } 746 747 NTSTATUS 748 KspAddObjectCreateItemToList( 749 PLIST_ENTRY ListHead, 750 IN PDRIVER_DISPATCH Create, 751 IN PVOID Context, 752 IN PWCHAR ObjectClass, 753 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 754 { 755 PLIST_ENTRY Entry; 756 PCREATE_ITEM_ENTRY CreateEntry; 757 758 /* point to first entry */ 759 Entry = ListHead->Flink; 760 761 while(Entry != ListHead) 762 { 763 /* get create entry */ 764 CreateEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry); 765 /* if the create item has no create routine, then it is free to use */ 766 if (CreateEntry->CreateItem->Create == NULL) 767 { 768 /* sanity check */ 769 ASSERT(IsListEmpty(&CreateEntry->ObjectItemList)); 770 ASSERT(CreateEntry->ReferenceCount == 0); 771 /* use free entry */ 772 CreateEntry->CreateItem->Context = Context; 773 CreateEntry->CreateItem->Create = Create; 774 RtlInitUnicodeString(&CreateEntry->CreateItem->ObjectClass, ObjectClass); 775 CreateEntry->CreateItem->SecurityDescriptor = SecurityDescriptor; 776 777 return STATUS_SUCCESS; 778 } 779 780 if (!wcsicmp(ObjectClass, CreateEntry->CreateItem->ObjectClass.Buffer)) 781 { 782 /* the same object class already exists */ 783 return STATUS_OBJECT_NAME_COLLISION; 784 } 785 786 /* iterate to next entry */ 787 Entry = Entry->Flink; 788 } 789 return STATUS_ALLOTTED_SPACE_EXCEEDED; 790 } 791 792 /* 793 @implemented 794 */ 795 KSDDKAPI 796 NTSTATUS 797 NTAPI 798 KsAddObjectCreateItemToDeviceHeader( 799 IN KSDEVICE_HEADER DevHeader, 800 IN PDRIVER_DISPATCH Create, 801 IN PVOID Context, 802 IN PWCHAR ObjectClass, 803 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 804 { 805 PKSIDEVICE_HEADER Header; 806 NTSTATUS Status; 807 808 Header = (PKSIDEVICE_HEADER)DevHeader; 809 810 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n"); 811 812 /* check if a device header has been provided */ 813 if (!DevHeader) 814 return STATUS_INVALID_PARAMETER_1; 815 816 /* check if a create item has been provided */ 817 if (!Create) 818 return STATUS_INVALID_PARAMETER_2; 819 820 /* check if a object class has been provided */ 821 if (!ObjectClass) 822 return STATUS_INVALID_PARAMETER_4; 823 824 /* let others do the work */ 825 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor); 826 827 if (NT_SUCCESS(Status)) 828 { 829 /* increment create item count */ 830 InterlockedIncrement(&Header->ItemListCount); 831 } 832 DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status); 833 return Status; 834 } 835 836 /* 837 @implemented 838 */ 839 KSDDKAPI 840 NTSTATUS 841 NTAPI 842 KsAddObjectCreateItemToObjectHeader( 843 IN KSOBJECT_HEADER ObjectHeader, 844 IN PDRIVER_DISPATCH Create, 845 IN PVOID Context, 846 IN PWCHAR ObjectClass, 847 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 848 { 849 PKSIOBJECT_HEADER Header; 850 NTSTATUS Status; 851 852 Header = (PKSIOBJECT_HEADER)ObjectHeader; 853 854 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n"); 855 856 /* check if a device header has been provided */ 857 if (!Header) 858 return STATUS_INVALID_PARAMETER_1; 859 860 /* check if a create item has been provided */ 861 if (!Create) 862 return STATUS_INVALID_PARAMETER_2; 863 864 /* check if a object class has been provided */ 865 if (!ObjectClass) 866 return STATUS_INVALID_PARAMETER_4; 867 868 /* let's work */ 869 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor); 870 871 if (NT_SUCCESS(Status)) 872 { 873 /* increment create item count */ 874 InterlockedIncrement(&Header->ItemListCount); 875 } 876 877 return Status; 878 } 879 880 /* 881 @implemented 882 */ 883 KSDDKAPI 884 NTSTATUS 885 NTAPI 886 KsAllocateObjectCreateItem( 887 IN KSDEVICE_HEADER DevHeader, 888 IN PKSOBJECT_CREATE_ITEM CreateItem, 889 IN BOOLEAN AllocateEntry, 890 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL) 891 { 892 PCREATE_ITEM_ENTRY CreateEntry; 893 PKSIDEVICE_HEADER Header; 894 PKSOBJECT_CREATE_ITEM Item; 895 896 Header = (PKSIDEVICE_HEADER)DevHeader; 897 898 if (!DevHeader) 899 return STATUS_INVALID_PARAMETER_1; 900 901 if (!CreateItem) 902 return STATUS_INVALID_PARAMETER_2; 903 904 /* first allocate a create entry */ 905 CreateEntry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY)); 906 907 /* check for allocation success */ 908 if (!CreateEntry) 909 { 910 /* not enough resources */ 911 return STATUS_INSUFFICIENT_RESOURCES; 912 } 913 914 915 if (AllocateEntry) 916 { 917 /* allocate create item */ 918 Item = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM)); 919 if (!Item) 920 { 921 /* no memory */ 922 FreeItem(CreateEntry); 923 return STATUS_INSUFFICIENT_RESOURCES; 924 } 925 926 /* initialize descriptor */ 927 Item->Context = CreateItem->Context; 928 Item->Create = CreateItem->Create; 929 Item->Flags = CreateItem->Flags; 930 Item->SecurityDescriptor = CreateItem->SecurityDescriptor; 931 Item->ObjectClass.Length = 0; 932 Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength; 933 934 /* copy object class */ 935 Item->ObjectClass.Buffer = AllocateItem(NonPagedPool, Item->ObjectClass.MaximumLength); 936 if (!Item->ObjectClass.Buffer) 937 { 938 /* release resources */ 939 FreeItem(Item); 940 FreeItem(CreateEntry); 941 942 return STATUS_INSUFFICIENT_RESOURCES; 943 } 944 RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass); 945 } 946 else 947 { 948 if (ItemFreeCallback) 949 { 950 /* callback is only accepted when the create item is copied */ 951 ItemFreeCallback = NULL; 952 } 953 /* use passed create item */ 954 Item = CreateItem; 955 } 956 957 /* initialize create item entry */ 958 InitializeListHead(&CreateEntry->ObjectItemList); 959 CreateEntry->ItemFreeCallback = ItemFreeCallback; 960 CreateEntry->CreateItem = Item; 961 CreateEntry->ReferenceCount = 0; 962 963 /* now insert the create item entry */ 964 InsertTailList(&Header->ItemList, &CreateEntry->Entry); 965 966 /* increment item count */ 967 InterlockedIncrement(&Header->ItemListCount); 968 969 return STATUS_SUCCESS; 970 } 971 972 NTSTATUS 973 KspObjectFreeCreateItems( 974 IN KSDEVICE_HEADER Header, 975 IN PKSOBJECT_CREATE_ITEM CreateItem) 976 { 977 UNIMPLEMENTED; 978 return STATUS_NOT_IMPLEMENTED; 979 } 980 981 /* 982 @implemented 983 */ 984 KSDDKAPI 985 NTSTATUS 986 NTAPI 987 KsFreeObjectCreateItem( 988 IN KSDEVICE_HEADER Header, 989 IN PUNICODE_STRING CreateItem) 990 { 991 KSOBJECT_CREATE_ITEM Item; 992 993 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM)); 994 RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer); 995 996 return KspObjectFreeCreateItems(Header, &Item); 997 } 998 999 1000 /* 1001 @implemented 1002 */ 1003 KSDDKAPI 1004 NTSTATUS 1005 NTAPI 1006 KsFreeObjectCreateItemsByContext( 1007 IN KSDEVICE_HEADER Header, 1008 IN PVOID Context) 1009 { 1010 KSOBJECT_CREATE_ITEM Item; 1011 1012 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM)); 1013 1014 Item.Context = Context; 1015 1016 return KspObjectFreeCreateItems(Header, &Item); 1017 } 1018 1019 /* 1020 @implemented 1021 */ 1022 KSDDKAPI 1023 NTSTATUS 1024 NTAPI 1025 KsCreateDefaultSecurity( 1026 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL, 1027 OUT PSECURITY_DESCRIPTOR* DefaultSecurity) 1028 { 1029 PGENERIC_MAPPING Mapping; 1030 SECURITY_SUBJECT_CONTEXT SubjectContext; 1031 NTSTATUS Status; 1032 1033 /* start capturing security context of calling thread */ 1034 SeCaptureSubjectContext(&SubjectContext); 1035 /* get generic mapping */ 1036 Mapping = IoGetFileObjectGenericMapping(); 1037 /* build new descriptor */ 1038 Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool); 1039 /* release security descriptor */ 1040 SeReleaseSubjectContext(&SubjectContext); 1041 /* done */ 1042 return Status; 1043 } 1044 1045 /* 1046 @unimplemented 1047 */ 1048 KSDDKAPI 1049 NTSTATUS 1050 NTAPI 1051 KsForwardIrp( 1052 IN PIRP Irp, 1053 IN PFILE_OBJECT FileObject, 1054 IN BOOLEAN ReuseStackLocation) 1055 { 1056 UNIMPLEMENTED; 1057 return STATUS_UNSUCCESSFUL; 1058 } 1059 1060 1061 /* 1062 @unimplemented 1063 */ 1064 KSDDKAPI 1065 NTSTATUS 1066 NTAPI 1067 KsForwardAndCatchIrp( 1068 IN PDEVICE_OBJECT DeviceObject, 1069 IN PIRP Irp, 1070 IN PFILE_OBJECT FileObject, 1071 IN KSSTACK_USE StackUse) 1072 { 1073 UNIMPLEMENTED; 1074 return STATUS_UNSUCCESSFUL; 1075 } 1076 1077 1078 NTSTATUS 1079 NTAPI 1080 KspSynchronousIoControlDeviceCompletion( 1081 IN PDEVICE_OBJECT DeviceObject, 1082 IN PIRP Irp, 1083 IN PVOID Context) 1084 { 1085 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context; 1086 1087 IoStatusBlock->Information = Irp->IoStatus.Information; 1088 IoStatusBlock->Status = Irp->IoStatus.Status; 1089 1090 return STATUS_SUCCESS; 1091 } 1092 1093 /* 1094 @implemented 1095 */ 1096 KSDDKAPI 1097 NTSTATUS 1098 NTAPI 1099 KsSynchronousIoControlDevice( 1100 IN PFILE_OBJECT FileObject, 1101 IN KPROCESSOR_MODE RequestorMode, 1102 IN ULONG IoControl, 1103 IN PVOID InBuffer, 1104 IN ULONG InSize, 1105 OUT PVOID OutBuffer, 1106 IN ULONG OutSize, 1107 OUT PULONG BytesReturned) 1108 { 1109 PKSIOBJECT_HEADER ObjectHeader; 1110 PDEVICE_OBJECT DeviceObject; 1111 KEVENT Event; 1112 PIRP Irp; 1113 IO_STATUS_BLOCK IoStatusBlock; 1114 PIO_STACK_LOCATION IoStack; 1115 NTSTATUS Status; 1116 1117 /* check for valid file object */ 1118 if (!FileObject) 1119 return STATUS_INVALID_PARAMETER; 1120 1121 /* get device object to send the request to */ 1122 DeviceObject = IoGetRelatedDeviceObject(FileObject); 1123 if (!DeviceObject) 1124 return STATUS_UNSUCCESSFUL; 1125 1126 1127 /* get object header */ 1128 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2; 1129 1130 /* check if there is fast device io function */ 1131 if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl) 1132 { 1133 IoStatusBlock.Status = STATUS_UNSUCCESSFUL; 1134 IoStatusBlock.Information = 0; 1135 1136 /* send the request */ 1137 Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject); 1138 /* check if the request was handled */ 1139 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information); 1140 if (Status) 1141 { 1142 /* store bytes returned */ 1143 *BytesReturned = (ULONG)IoStatusBlock.Information; 1144 /* return status */ 1145 return IoStatusBlock.Status; 1146 } 1147 } 1148 1149 /* initialize the event */ 1150 KeInitializeEvent(&Event, NotificationEvent, FALSE); 1151 1152 /* create the irp */ 1153 Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock); 1154 1155 if (!Irp) 1156 { 1157 /* no memory to allocate the irp */ 1158 return STATUS_INSUFFICIENT_RESOURCES; 1159 } 1160 1161 1162 /* Store Fileobject */ 1163 IoStack = IoGetNextIrpStackLocation(Irp); 1164 IoStack->FileObject = FileObject; 1165 1166 if (IoControl == IOCTL_KS_WRITE_STREAM) 1167 { 1168 Irp->AssociatedIrp.SystemBuffer = OutBuffer; 1169 } 1170 else if (IoControl == IOCTL_KS_READ_STREAM) 1171 { 1172 Irp->AssociatedIrp.SystemBuffer = InBuffer; 1173 } 1174 1175 IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE); 1176 1177 Status = IoCallDriver(DeviceObject, Irp); 1178 if (Status == STATUS_PENDING) 1179 { 1180 KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL); 1181 Status = IoStatusBlock.Status; 1182 } 1183 1184 *BytesReturned = (ULONG)IoStatusBlock.Information; 1185 return Status; 1186 } 1187 1188 /* 1189 @unimplemented 1190 */ 1191 KSDDKAPI 1192 NTSTATUS 1193 NTAPI 1194 KsUnserializeObjectPropertiesFromRegistry( 1195 IN PFILE_OBJECT FileObject, 1196 IN HANDLE ParentKey OPTIONAL, 1197 IN PUNICODE_STRING RegistryPath OPTIONAL) 1198 { 1199 UNIMPLEMENTED; 1200 return STATUS_NOT_IMPLEMENTED; 1201 } 1202 1203 1204 /* 1205 @implemented 1206 */ 1207 KSDDKAPI 1208 NTSTATUS 1209 NTAPI 1210 KsCacheMedium( 1211 IN PUNICODE_STRING SymbolicLink, 1212 IN PKSPIN_MEDIUM Medium, 1213 IN ULONG PinDirection) 1214 { 1215 HANDLE hKey; 1216 UNICODE_STRING Path; 1217 UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\"); 1218 UNICODE_STRING GuidString; 1219 NTSTATUS Status; 1220 OBJECT_ATTRIBUTES ObjectAttributes; 1221 BOOLEAN PathAdjusted = FALSE; 1222 ULONG Value = 0; 1223 1224 /* first check if the medium is standard */ 1225 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) || 1226 IsEqualGUIDAligned(&GUID_NULL, &Medium->Set)) 1227 { 1228 /* no need to cache that */ 1229 return STATUS_SUCCESS; 1230 } 1231 1232 /* convert guid to string */ 1233 Status = RtlStringFromGUID(&Medium->Set, &GuidString); 1234 if (!NT_SUCCESS(Status)) 1235 return Status; 1236 1237 /* allocate path buffer */ 1238 Path.Length = 0; 1239 Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR); 1240 Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength); 1241 if (!Path.Buffer) 1242 { 1243 /* not enough resources */ 1244 RtlFreeUnicodeString(&GuidString); 1245 return STATUS_INSUFFICIENT_RESOURCES; 1246 } 1247 1248 RtlAppendUnicodeStringToString(&Path, &BasePath); 1249 RtlAppendUnicodeStringToString(&Path, &GuidString); 1250 RtlAppendUnicodeToString(&Path, L"-"); 1251 /* FIXME append real instance id */ 1252 RtlAppendUnicodeToString(&Path, L"0"); 1253 RtlAppendUnicodeToString(&Path, L"-"); 1254 /* FIXME append real instance id */ 1255 RtlAppendUnicodeToString(&Path, L"0"); 1256 1257 /* free guid string */ 1258 RtlFreeUnicodeString(&GuidString); 1259 1260 /* initialize object attributes */ 1261 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 1262 /* create the key */ 1263 Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 1264 1265 /* free path buffer */ 1266 FreeItem(Path.Buffer); 1267 1268 if (NT_SUCCESS(Status)) 1269 { 1270 /* store symbolic link */ 1271 if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?') 1272 { 1273 /* replace kernel path with user mode path */ 1274 SymbolicLink->Buffer[1] = L'\\'; 1275 PathAdjusted = TRUE; 1276 } 1277 1278 /* store the key */ 1279 Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG)); 1280 1281 if (PathAdjusted) 1282 { 1283 /* restore kernel path */ 1284 SymbolicLink->Buffer[1] = L'?'; 1285 } 1286 1287 ZwClose(hKey); 1288 } 1289 1290 /* done */ 1291 return Status; 1292 } 1293 1294 /* 1295 @implemented 1296 */ 1297 NTSTATUS 1298 NTAPI 1299 DllInitialize( 1300 PUNICODE_STRING RegistryPath) 1301 { 1302 return STATUS_SUCCESS; 1303 } 1304 1305 1306 NTSTATUS 1307 NTAPI 1308 KopDispatchClose( 1309 IN PDEVICE_OBJECT DeviceObject, 1310 IN PIRP Irp) 1311 { 1312 PKO_OBJECT_HEADER Header; 1313 PIO_STACK_LOCATION IoStack; 1314 PDEVICE_EXTENSION DeviceExtension; 1315 1316 /* get current irp stack location */ 1317 IoStack = IoGetCurrentIrpStackLocation(Irp); 1318 1319 /* get ko object header */ 1320 Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2; 1321 1322 /* free ks object header */ 1323 KsFreeObjectHeader(Header->ObjectHeader); 1324 1325 /* free ko object header */ 1326 FreeItem(Header); 1327 1328 /* get device extension */ 1329 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 1330 1331 /* release bus object */ 1332 KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader); 1333 1334 /* complete request */ 1335 Irp->IoStatus.Status = STATUS_SUCCESS; 1336 CompleteRequest(Irp, IO_NO_INCREMENT); 1337 1338 return STATUS_SUCCESS; 1339 } 1340 1341 1342 1343 static KSDISPATCH_TABLE KoDispatchTable = 1344 { 1345 KsDispatchInvalidDeviceRequest, 1346 KsDispatchInvalidDeviceRequest, 1347 KsDispatchInvalidDeviceRequest, 1348 KsDispatchInvalidDeviceRequest, 1349 KopDispatchClose, 1350 KsDispatchQuerySecurity, 1351 KsDispatchSetSecurity, 1352 KsDispatchFastIoDeviceControlFailure, 1353 KsDispatchFastReadFailure, 1354 KsDispatchFastReadFailure, 1355 }; 1356 1357 1358 NTSTATUS 1359 NTAPI 1360 KopDispatchCreate( 1361 IN PDEVICE_OBJECT DeviceObject, 1362 IN PIRP Irp) 1363 { 1364 PKO_OBJECT_HEADER Header = NULL; 1365 PIO_STACK_LOCATION IoStack; 1366 PKO_DRIVER_EXTENSION DriverObjectExtension; 1367 NTSTATUS Status; 1368 1369 /* get current irp stack location */ 1370 IoStack = IoGetCurrentIrpStackLocation(Irp); 1371 1372 if (!IoStack->FileObject) 1373 { 1374 DPRINT1("FileObject not attached!\n"); 1375 Status = STATUS_UNSUCCESSFUL; 1376 goto cleanup; 1377 } 1378 1379 /* get driver object extension */ 1380 DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize); 1381 if (!DriverObjectExtension) 1382 { 1383 DPRINT1("No DriverObjectExtension!\n"); 1384 Status = STATUS_UNSUCCESSFUL; 1385 goto cleanup; 1386 } 1387 1388 /* allocate ko object header */ 1389 Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER)); 1390 if (!Header) 1391 { 1392 DPRINT1("failed to allocate KO_OBJECT_HEADER\n"); 1393 Status = STATUS_INSUFFICIENT_RESOURCES; 1394 goto cleanup; 1395 } 1396 1397 /* initialize create item */ 1398 Header->CreateItem.Create = KopDispatchCreate; 1399 RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject); 1400 1401 1402 /* now allocate the object header */ 1403 Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable); 1404 if (!NT_SUCCESS(Status)) 1405 { 1406 /* failed */ 1407 goto cleanup; 1408 } 1409 1410 /* FIXME 1411 * extract clsid and interface id from irp 1412 * call the standard create handler 1413 */ 1414 1415 UNIMPLEMENTED; 1416 1417 IoStack->FileObject->FsContext2 = (PVOID)Header; 1418 1419 Irp->IoStatus.Status = Status; 1420 CompleteRequest(Irp, IO_NO_INCREMENT); 1421 1422 return Status; 1423 1424 cleanup: 1425 1426 if (Header && Header->ObjectHeader) 1427 KsFreeObjectHeader(Header->ObjectHeader); 1428 1429 if (Header) 1430 FreeItem(Header); 1431 1432 Irp->IoStatus.Status = Status; 1433 CompleteRequest(Irp, IO_NO_INCREMENT); 1434 return Status; 1435 } 1436 1437 1438 1439 NTSTATUS 1440 NTAPI 1441 KopAddDevice( 1442 IN PDRIVER_OBJECT DriverObject, 1443 IN PDEVICE_OBJECT PhysicalDeviceObject) 1444 { 1445 NTSTATUS Status = STATUS_DEVICE_REMOVED; 1446 PDEVICE_OBJECT FunctionalDeviceObject= NULL; 1447 PDEVICE_OBJECT NextDeviceObject; 1448 PDEVICE_EXTENSION DeviceExtension; 1449 PKSOBJECT_CREATE_ITEM CreateItem; 1450 1451 /* create the device object */ 1452 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject); 1453 if (!NT_SUCCESS(Status)) 1454 return Status; 1455 1456 /* allocate the create item */ 1457 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM)); 1458 1459 if (!CreateItem) 1460 { 1461 /* not enough memory */ 1462 IoDeleteDevice(FunctionalDeviceObject); 1463 return STATUS_INSUFFICIENT_RESOURCES; 1464 } 1465 1466 /* initialize create item */ 1467 CreateItem->Create = KopDispatchCreate; 1468 RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject); 1469 1470 /* get device extension */ 1471 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension; 1472 1473 /* now allocate the device header */ 1474 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem); 1475 if (!NT_SUCCESS(Status)) 1476 { 1477 /* failed */ 1478 IoDeleteDevice(FunctionalDeviceObject); 1479 FreeItem(CreateItem); 1480 return Status; 1481 } 1482 1483 /* now attach to device stack */ 1484 NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject); 1485 if (NextDeviceObject) 1486 { 1487 /* store pnp base object */ 1488 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject); 1489 /* set device flags */ 1490 FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; 1491 FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; 1492 } 1493 else 1494 { 1495 /* failed */ 1496 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader); 1497 FreeItem(CreateItem); 1498 IoDeleteDevice(FunctionalDeviceObject); 1499 Status = STATUS_DEVICE_REMOVED; 1500 } 1501 1502 /* return result */ 1503 return Status; 1504 } 1505 1506 1507 /* 1508 @implemented 1509 */ 1510 COMDDKAPI 1511 NTSTATUS 1512 NTAPI 1513 KoDeviceInitialize( 1514 IN PDEVICE_OBJECT DeviceObject) 1515 { 1516 PDEVICE_EXTENSION DeviceExtension; 1517 1518 /* get device extension */ 1519 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 1520 1521 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL); 1522 } 1523 1524 /* 1525 @implemented 1526 */ 1527 COMDDKAPI 1528 NTSTATUS 1529 NTAPI 1530 KoDriverInitialize( 1531 IN PDRIVER_OBJECT DriverObject, 1532 IN PUNICODE_STRING RegistryPathName, 1533 IN KoCreateObjectHandler CreateObjectHandler) 1534 { 1535 PKO_DRIVER_EXTENSION DriverObjectExtension; 1536 NTSTATUS Status; 1537 1538 /* allocate driver object extension */ 1539 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension); 1540 1541 /* did it work */ 1542 if (NT_SUCCESS(Status)) 1543 { 1544 /* store create handler */ 1545 DriverObjectExtension->CreateObjectHandler = CreateObjectHandler; 1546 1547 /* Setting our IRP handlers */ 1548 DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp; 1549 DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower; 1550 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp; 1551 1552 /* The driver unload routine */ 1553 DriverObject->DriverUnload = KsNullDriverUnload; 1554 1555 /* The driver-supplied AddDevice */ 1556 DriverObject->DriverExtension->AddDevice = KopAddDevice; 1557 1558 /* KS handles these */ 1559 DPRINT1("Setting KS function handlers\n"); 1560 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE); 1561 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE); 1562 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL); 1563 1564 } 1565 1566 return Status; 1567 } 1568 1569 /* 1570 @unimplemented 1571 */ 1572 COMDDKAPI 1573 VOID 1574 NTAPI 1575 KoRelease( 1576 IN REFCLSID ClassId) 1577 { 1578 1579 } 1580 1581 /* 1582 @implemented 1583 */ 1584 KSDDKAPI 1585 VOID 1586 NTAPI 1587 KsAcquireControl( 1588 IN PVOID Object) 1589 { 1590 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 1591 1592 /* sanity check */ 1593 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); 1594 1595 KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL); 1596 1597 } 1598 1599 /* 1600 @implemented 1601 */ 1602 VOID 1603 NTAPI 1604 KsReleaseControl( 1605 IN PVOID Object) 1606 { 1607 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 1608 1609 /* sanity check */ 1610 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); 1611 1612 KeReleaseMutex(BasicHeader->ControlMutex, FALSE); 1613 } 1614 1615 1616 1617 /* 1618 @implemented 1619 */ 1620 KSDDKAPI 1621 VOID 1622 NTAPI 1623 KsAcquireDevice( 1624 IN PKSDEVICE Device) 1625 { 1626 IKsDevice *KsDevice; 1627 PKSIDEVICE_HEADER DeviceHeader; 1628 1629 DPRINT("KsAcquireDevice\n"); 1630 DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); 1631 1632 /* get device interface*/ 1633 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown; 1634 1635 /* acquire device mutex */ 1636 KsDevice->lpVtbl->AcquireDevice(KsDevice); 1637 } 1638 1639 /* 1640 @implemented 1641 */ 1642 VOID 1643 NTAPI 1644 KsReleaseDevice( 1645 IN PKSDEVICE Device) 1646 { 1647 IKsDevice *KsDevice; 1648 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); 1649 1650 /* get device interface*/ 1651 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown; 1652 1653 /* release device mutex */ 1654 KsDevice->lpVtbl->ReleaseDevice(KsDevice); 1655 } 1656 1657 /* 1658 @implemented 1659 */ 1660 KSDDKAPI 1661 VOID 1662 NTAPI 1663 KsTerminateDevice( 1664 IN PDEVICE_OBJECT DeviceObject) 1665 { 1666 IKsDevice *KsDevice; 1667 PKSIDEVICE_HEADER DeviceHeader; 1668 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 1669 1670 /* get device header */ 1671 DeviceHeader = DeviceExtension->DeviceHeader; 1672 1673 /* get device interface*/ 1674 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown; 1675 1676 /* now free device header */ 1677 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader); 1678 1679 /* release interface when available */ 1680 if (KsDevice) 1681 { 1682 /* delete IKsDevice interface */ 1683 KsDevice->lpVtbl->Release(KsDevice); 1684 } 1685 } 1686 1687 /* 1688 @implemented 1689 */ 1690 KSDDKAPI 1691 VOID 1692 NTAPI 1693 KsCompletePendingRequest( 1694 IN PIRP Irp) 1695 { 1696 PIO_STACK_LOCATION IoStack; 1697 1698 /* get current irp stack location */ 1699 IoStack = IoGetCurrentIrpStackLocation(Irp); 1700 1701 /* sanity check */ 1702 ASSERT(Irp->IoStatus.Status != STATUS_PENDING); 1703 1704 if (IoStack->MajorFunction != IRP_MJ_CLOSE) 1705 { 1706 /* can be completed immediately */ 1707 CompleteRequest(Irp, IO_NO_INCREMENT); 1708 return; 1709 } 1710 1711 /* did close operation fail */ 1712 if (!NT_SUCCESS(Irp->IoStatus.Status)) 1713 { 1714 /* closing failed, complete irp */ 1715 CompleteRequest(Irp, IO_NO_INCREMENT); 1716 return; 1717 } 1718 1719 /* FIXME 1720 * delete object / device header 1721 * remove dead pin / filter instance 1722 */ 1723 UNIMPLEMENTED; 1724 1725 } 1726 1727 NTSTATUS 1728 NTAPI 1729 KspSetGetBusDataCompletion( 1730 IN PDEVICE_OBJECT DeviceObject, 1731 IN PIRP Irp, 1732 IN PVOID Context) 1733 { 1734 /* signal completion */ 1735 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE); 1736 1737 /* more work needs be done, so dont free the irp */ 1738 return STATUS_MORE_PROCESSING_REQUIRED; 1739 1740 } 1741 1742 NTSTATUS 1743 KspDeviceSetGetBusData( 1744 IN PDEVICE_OBJECT DeviceObject, 1745 IN ULONG DataType, 1746 IN PVOID Buffer, 1747 IN ULONG Offset, 1748 IN ULONG Length, 1749 IN BOOL bGet) 1750 { 1751 PIO_STACK_LOCATION IoStack; 1752 PIRP Irp; 1753 NTSTATUS Status; 1754 KEVENT Event; 1755 1756 /* allocate the irp */ 1757 Irp = IoAllocateIrp(1, /*FIXME */ 1758 FALSE); 1759 1760 if (!Irp) 1761 return STATUS_INSUFFICIENT_RESOURCES; 1762 1763 /* initialize the event */ 1764 KeInitializeEvent(&Event, NotificationEvent, FALSE); 1765 1766 /* get next stack location */ 1767 IoStack = IoGetNextIrpStackLocation(Irp); 1768 1769 /* setup a completion routine */ 1770 IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE); 1771 1772 /* setup parameters */ 1773 IoStack->Parameters.ReadWriteConfig.Buffer = Buffer; 1774 IoStack->Parameters.ReadWriteConfig.Length = Length; 1775 IoStack->Parameters.ReadWriteConfig.Offset = Offset; 1776 IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType; 1777 /* setup function code */ 1778 IoStack->MajorFunction = IRP_MJ_PNP; 1779 IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG); 1780 1781 /* lets call the driver */ 1782 Status = IoCallDriver(DeviceObject, Irp); 1783 1784 /* is the request still pending */ 1785 if (Status == STATUS_PENDING) 1786 { 1787 /* have a nap */ 1788 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1789 /* update status */ 1790 Status = Irp->IoStatus.Status; 1791 } 1792 1793 /* free the irp */ 1794 IoFreeIrp(Irp); 1795 /* done */ 1796 return Status; 1797 } 1798 1799 /* 1800 @implemented 1801 */ 1802 KSDDKAPI 1803 ULONG 1804 NTAPI 1805 KsDeviceSetBusData( 1806 IN PKSDEVICE Device, 1807 IN ULONG DataType, 1808 IN PVOID Buffer, 1809 IN ULONG Offset, 1810 IN ULONG Length) 1811 { 1812 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */ 1813 DataType, Buffer, Offset, Length, FALSE); 1814 } 1815 1816 1817 /* 1818 @implemented 1819 */ 1820 KSDDKAPI 1821 ULONG 1822 NTAPI 1823 KsDeviceGetBusData( 1824 IN PKSDEVICE Device, 1825 IN ULONG DataType, 1826 IN PVOID Buffer, 1827 IN ULONG Offset, 1828 IN ULONG Length) 1829 { 1830 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */ 1831 DataType, Buffer, Offset, Length, TRUE); 1832 1833 } 1834 1835 /* 1836 @implemented 1837 */ 1838 KSDDKAPI 1839 void 1840 NTAPI 1841 KsDeviceRegisterAdapterObject( 1842 IN PKSDEVICE Device, 1843 IN PADAPTER_OBJECT AdapterObject, 1844 IN ULONG MaxMappingsByteCount, 1845 IN ULONG MappingTableStride) 1846 { 1847 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); 1848 1849 DeviceHeader->AdapterObject = AdapterObject; 1850 DeviceHeader->MaxMappingsByteCount = MaxMappingsByteCount; 1851 DeviceHeader->MappingTableStride = MappingTableStride; 1852 1853 } 1854 1855 1856 /* 1857 @implemented 1858 */ 1859 KSDDKAPI 1860 PVOID 1861 NTAPI 1862 KsGetFirstChild( 1863 IN PVOID Object) 1864 { 1865 PKSBASIC_HEADER BasicHeader; 1866 1867 /* get the basic header */ 1868 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 1869 1870 /* type has to be either a device or a filter factory */ 1871 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory); 1872 1873 return (PVOID)BasicHeader->FirstChild.Filter; 1874 } 1875 1876 /* 1877 @implemented 1878 */ 1879 KSDDKAPI 1880 PVOID 1881 NTAPI 1882 KsGetNextSibling( 1883 IN PVOID Object) 1884 { 1885 PKSBASIC_HEADER BasicHeader; 1886 1887 /* get the basic header */ 1888 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 1889 1890 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 1891 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); 1892 1893 return (PVOID)BasicHeader->Next.Pin; 1894 } 1895 1896 ULONG 1897 KspCountMethodSets( 1898 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 1899 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL) 1900 { 1901 ULONG Index, SubIndex, Count; 1902 BOOL bFound; 1903 1904 if (!AutomationTableA) 1905 return AutomationTableB->MethodSetsCount; 1906 1907 if (!AutomationTableB) 1908 return AutomationTableA->MethodSetsCount; 1909 1910 1911 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA->MethodItemSize, AutomationTableA->MethodSetsCount); 1912 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB->MethodItemSize, AutomationTableB->MethodSetsCount); 1913 1914 if (AutomationTableA->MethodItemSize && AutomationTableB->MethodItemSize) 1915 { 1916 /* sanity check */ 1917 ASSERT(AutomationTableA->MethodItemSize == AutomationTableB->MethodItemSize); 1918 } 1919 1920 /* now iterate all property sets and compare their guids */ 1921 Count = AutomationTableA->MethodSetsCount; 1922 1923 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++) 1924 { 1925 /* set found to false */ 1926 bFound = FALSE; 1927 1928 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++) 1929 { 1930 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set)) 1931 { 1932 /* same property set found */ 1933 bFound = TRUE; 1934 break; 1935 } 1936 } 1937 1938 if (!bFound) 1939 Count++; 1940 } 1941 1942 return Count; 1943 } 1944 1945 ULONG 1946 KspCountEventSets( 1947 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 1948 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL) 1949 { 1950 ULONG Index, SubIndex, Count; 1951 BOOL bFound; 1952 1953 if (!AutomationTableA) 1954 return AutomationTableB->EventSetsCount; 1955 1956 if (!AutomationTableB) 1957 return AutomationTableA->EventSetsCount; 1958 1959 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA->EventItemSize, AutomationTableA->EventSetsCount); 1960 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB->EventItemSize, AutomationTableB->EventSetsCount); 1961 1962 if (AutomationTableA->EventItemSize && AutomationTableB->EventItemSize) 1963 { 1964 /* sanity check */ 1965 ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize); 1966 } 1967 1968 /* now iterate all Event sets and compare their guids */ 1969 Count = AutomationTableA->EventSetsCount; 1970 1971 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++) 1972 { 1973 /* set found to false */ 1974 bFound = FALSE; 1975 1976 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++) 1977 { 1978 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set)) 1979 { 1980 /* same Event set found */ 1981 bFound = TRUE; 1982 break; 1983 } 1984 } 1985 1986 if (!bFound) 1987 Count++; 1988 } 1989 1990 return Count; 1991 } 1992 1993 1994 ULONG 1995 KspCountPropertySets( 1996 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 1997 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL) 1998 { 1999 ULONG Index, SubIndex, Count; 2000 BOOL bFound; 2001 2002 if (!AutomationTableA) 2003 return AutomationTableB->PropertySetsCount; 2004 2005 if (!AutomationTableB) 2006 return AutomationTableA->PropertySetsCount; 2007 2008 /* sanity check */ 2009 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA->PropertyItemSize, AutomationTableA->PropertySetsCount); 2010 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB->PropertyItemSize, AutomationTableB->PropertySetsCount); 2011 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize); 2012 2013 /* now iterate all property sets and compare their guids */ 2014 Count = AutomationTableA->PropertySetsCount; 2015 2016 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++) 2017 { 2018 /* set found to false */ 2019 bFound = FALSE; 2020 2021 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++) 2022 { 2023 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set)) 2024 { 2025 /* same property set found */ 2026 bFound = TRUE; 2027 break; 2028 } 2029 } 2030 2031 if (!bFound) 2032 Count++; 2033 } 2034 2035 return Count; 2036 } 2037 2038 NTSTATUS 2039 KspCopyMethodSets( 2040 OUT PKSAUTOMATION_TABLE Table, 2041 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 2042 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL) 2043 { 2044 ULONG Index, SubIndex, Count; 2045 BOOL bFound; 2046 2047 if (!AutomationTableA) 2048 { 2049 /* copy of property set */ 2050 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableB->MethodSetsCount); 2051 return STATUS_SUCCESS; 2052 } 2053 else if (!AutomationTableB) 2054 { 2055 /* copy of property set */ 2056 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount); 2057 return STATUS_SUCCESS; 2058 } 2059 2060 /* first copy all property items from dominant table */ 2061 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount); 2062 /* set counter */ 2063 Count = AutomationTableA->MethodSetsCount; 2064 2065 /* now copy entries which aren't available in the dominant table */ 2066 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++) 2067 { 2068 /* set found to false */ 2069 bFound = FALSE; 2070 2071 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++) 2072 { 2073 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set)) 2074 { 2075 /* same property set found */ 2076 bFound = TRUE; 2077 break; 2078 } 2079 } 2080 2081 if (!bFound) 2082 { 2083 /* copy new property item set */ 2084 RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], sizeof(KSMETHOD_SET)); 2085 Count++; 2086 } 2087 } 2088 2089 return STATUS_SUCCESS; 2090 } 2091 2092 VOID 2093 KspAddPropertyItem( 2094 OUT PKSPROPERTY_SET OutPropertySet, 2095 IN PKSPROPERTY_ITEM PropertyItem, 2096 IN ULONG PropertyItemSize) 2097 { 2098 PKSPROPERTY_ITEM CurrentPropertyItem; 2099 ULONG Index; 2100 2101 // check if the property item is already present 2102 CurrentPropertyItem = (PKSPROPERTY_ITEM)OutPropertySet->PropertyItem; 2103 for(Index = 0; Index < OutPropertySet->PropertiesCount; Index++) 2104 { 2105 if (CurrentPropertyItem->PropertyId == PropertyItem->PropertyId) 2106 { 2107 // item already present 2108 return; 2109 } 2110 2111 // next item 2112 CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + PropertyItemSize); 2113 } 2114 // add item 2115 RtlCopyMemory(CurrentPropertyItem, PropertyItem, PropertyItemSize); 2116 OutPropertySet->PropertiesCount++; 2117 } 2118 2119 NTSTATUS 2120 KspMergePropertySet( 2121 OUT PKSAUTOMATION_TABLE Table, 2122 OUT PKSPROPERTY_SET OutPropertySet, 2123 IN PKSPROPERTY_SET PropertySetA, 2124 IN PKSPROPERTY_SET PropertySetB, 2125 IN KSOBJECT_BAG Bag OPTIONAL) 2126 { 2127 ULONG PropertyCount, Index; 2128 PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem; 2129 NTSTATUS Status; 2130 2131 // max properties 2132 PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount; 2133 2134 // allocate items 2135 PropertyItem = AllocateItem(NonPagedPool, Table->PropertyItemSize * PropertyCount); 2136 if (!PropertyItem) 2137 return STATUS_INSUFFICIENT_RESOURCES; 2138 2139 if (Bag) 2140 { 2141 /* add table to object bag */ 2142 Status = KsAddItemToObjectBag(Bag, PropertyItem, NULL); 2143 /* check for success */ 2144 if (!NT_SUCCESS(Status)) 2145 { 2146 /* free table */ 2147 FreeItem(Table); 2148 return Status; 2149 } 2150 } 2151 2152 // copy entries from dominant table 2153 RtlCopyMemory(PropertyItem, PropertySetA->PropertyItem, Table->PropertyItemSize * PropertySetA->PropertiesCount); 2154 2155 // init property set 2156 OutPropertySet->PropertiesCount = PropertySetA->PropertiesCount; 2157 OutPropertySet->PropertyItem = PropertyItem; 2158 2159 // copy other entries 2160 CurrentPropertyItem = (PKSPROPERTY_ITEM)PropertySetB->PropertyItem; 2161 for(Index = 0; Index < PropertySetB->PropertiesCount; Index++) 2162 { 2163 2164 // add entries 2165 KspAddPropertyItem(OutPropertySet, CurrentPropertyItem, Table->PropertyItemSize); 2166 2167 // next entry 2168 CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + Table->PropertyItemSize); 2169 } 2170 2171 // done 2172 return STATUS_SUCCESS; 2173 } 2174 2175 2176 NTSTATUS 2177 KspCopyPropertySets( 2178 OUT PKSAUTOMATION_TABLE Table, 2179 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 2180 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL, 2181 IN KSOBJECT_BAG Bag OPTIONAL) 2182 { 2183 ULONG Index, SubIndex, Count; 2184 BOOL bFound; 2185 NTSTATUS Status; 2186 2187 if (!AutomationTableA) 2188 { 2189 /* copy of property set */ 2190 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableB->PropertySetsCount); 2191 return STATUS_SUCCESS; 2192 } 2193 else if (!AutomationTableB) 2194 { 2195 /* copy of property set */ 2196 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount); 2197 return STATUS_SUCCESS; 2198 } 2199 2200 /* first copy all property items from dominant table */ 2201 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount); 2202 /* set counter */ 2203 Count = AutomationTableA->PropertySetsCount; 2204 2205 /* now copy entries which aren't available in the dominant table */ 2206 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++) 2207 { 2208 /* set found to false */ 2209 bFound = FALSE; 2210 2211 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++) 2212 { 2213 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set)) 2214 { 2215 /* same property set found */ 2216 bFound = TRUE; 2217 break; 2218 } 2219 } 2220 2221 if (!bFound) 2222 { 2223 /* copy new property item set */ 2224 RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], sizeof(KSPROPERTY_SET)); 2225 Count++; 2226 } 2227 else 2228 { 2229 // merge property sets 2230 Status = KspMergePropertySet(Table, (PKSPROPERTY_SET)&Table->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableA->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableB->PropertySets[Index], Bag); 2231 if (!NT_SUCCESS(Status)) 2232 { 2233 // failed to merge 2234 DPRINT1("[KS] Failed to merge %x\n", Status); 2235 return Status; 2236 } 2237 } 2238 } 2239 2240 return STATUS_SUCCESS; 2241 } 2242 2243 NTSTATUS 2244 KspCopyEventSets( 2245 OUT PKSAUTOMATION_TABLE Table, 2246 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 2247 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL) 2248 { 2249 ULONG Index, SubIndex, Count; 2250 BOOL bFound; 2251 2252 if (!AutomationTableA) 2253 { 2254 /* copy of Event set */ 2255 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, sizeof(KSEVENT_SET) * AutomationTableB->EventSetsCount); 2256 return STATUS_SUCCESS; 2257 } 2258 else if (!AutomationTableB) 2259 { 2260 /* copy of Event set */ 2261 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount); 2262 return STATUS_SUCCESS; 2263 } 2264 2265 /* first copy all Event items from dominant table */ 2266 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount); 2267 /* set counter */ 2268 Count = AutomationTableA->EventSetsCount; 2269 2270 /* now copy entries which aren't available in the dominant table */ 2271 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++) 2272 { 2273 /* set found to false */ 2274 bFound = FALSE; 2275 2276 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++) 2277 { 2278 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set)) 2279 { 2280 /* same Event set found */ 2281 bFound = TRUE; 2282 break; 2283 } 2284 } 2285 2286 if (!bFound) 2287 { 2288 /* copy new Event item set */ 2289 RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], sizeof(KSEVENT_SET)); 2290 Count++; 2291 } 2292 } 2293 2294 return STATUS_SUCCESS; 2295 } 2296 2297 2298 /* 2299 @implemented 2300 */ 2301 NTSTATUS 2302 NTAPI 2303 KsMergeAutomationTables( 2304 OUT PKSAUTOMATION_TABLE *AutomationTableAB, 2305 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL, 2306 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL, 2307 IN KSOBJECT_BAG Bag OPTIONAL) 2308 { 2309 PKSAUTOMATION_TABLE Table; 2310 NTSTATUS Status = STATUS_SUCCESS; 2311 2312 if (!AutomationTableA && !AutomationTableB) 2313 { 2314 /* nothing to merge */ 2315 return STATUS_SUCCESS; 2316 } 2317 2318 /* allocate an automation table */ 2319 Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE)); 2320 if (!Table) 2321 return STATUS_INSUFFICIENT_RESOURCES; 2322 2323 if (Bag) 2324 { 2325 /* add table to object bag */ 2326 Status = KsAddItemToObjectBag(Bag, Table, NULL); 2327 /* check for success */ 2328 if (!NT_SUCCESS(Status)) 2329 { 2330 /* free table */ 2331 FreeItem(Table); 2332 return Status; 2333 } 2334 } 2335 2336 /* count property sets */ 2337 Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB); 2338 2339 if (Table->PropertySetsCount) 2340 { 2341 if (AutomationTableA) 2342 { 2343 /* use item size from dominant automation table */ 2344 Table->PropertyItemSize = AutomationTableA->PropertyItemSize; 2345 } 2346 else 2347 { 2348 /* use item size from 2nd automation table */ 2349 Table->PropertyItemSize = AutomationTableB->PropertyItemSize; 2350 } 2351 2352 if (AutomationTableA && AutomationTableB) 2353 { 2354 // FIXME handle different property item sizes 2355 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize); 2356 } 2357 2358 /* now allocate the property sets */ 2359 Table->PropertySets = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * Table->PropertySetsCount); 2360 2361 if (!Table->PropertySets) 2362 { 2363 /* not enough memory */ 2364 goto cleanup; 2365 } 2366 2367 if (Bag) 2368 { 2369 /* add set to property bag */ 2370 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL); 2371 /* check for success */ 2372 if (!NT_SUCCESS(Status)) 2373 { 2374 /* cleanup table */ 2375 goto cleanup; 2376 } 2377 } 2378 /* now copy the property sets */ 2379 Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB, Bag); 2380 if(!NT_SUCCESS(Status)) 2381 goto cleanup; 2382 2383 } 2384 2385 /* now count the method sets */ 2386 Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB); 2387 2388 if (Table->MethodSetsCount) 2389 { 2390 if (AutomationTableA) 2391 { 2392 /* use item size from dominant automation table */ 2393 Table->MethodItemSize = AutomationTableA->MethodItemSize; 2394 } 2395 else 2396 { 2397 /* use item size from 2nd automation table */ 2398 Table->MethodItemSize = AutomationTableB->MethodItemSize; 2399 } 2400 2401 /* now allocate the property sets */ 2402 Table->MethodSets = AllocateItem(NonPagedPool, sizeof(KSMETHOD_SET) * Table->MethodSetsCount); 2403 2404 if (!Table->MethodSets) 2405 { 2406 /* not enough memory */ 2407 goto cleanup; 2408 } 2409 2410 if (Bag) 2411 { 2412 /* add set to property bag */ 2413 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL); 2414 /* check for success */ 2415 if (!NT_SUCCESS(Status)) 2416 { 2417 /* cleanup table */ 2418 goto cleanup; 2419 } 2420 } 2421 /* now copy the property sets */ 2422 Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB); 2423 if(!NT_SUCCESS(Status)) 2424 goto cleanup; 2425 } 2426 2427 2428 /* now count the event sets */ 2429 Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB); 2430 2431 if (Table->EventSetsCount) 2432 { 2433 if (AutomationTableA) 2434 { 2435 /* use item size from dominant automation table */ 2436 Table->EventItemSize = AutomationTableA->EventItemSize; 2437 } 2438 else 2439 { 2440 /* use item size from 2nd automation table */ 2441 Table->EventItemSize = AutomationTableB->EventItemSize; 2442 } 2443 2444 /* now allocate the property sets */ 2445 Table->EventSets = AllocateItem(NonPagedPool, sizeof(KSEVENT_SET) * Table->EventSetsCount); 2446 2447 if (!Table->EventSets) 2448 { 2449 /* not enough memory */ 2450 goto cleanup; 2451 } 2452 2453 if (Bag) 2454 { 2455 /* add set to property bag */ 2456 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL); 2457 /* check for success */ 2458 if (!NT_SUCCESS(Status)) 2459 { 2460 /* cleanup table */ 2461 goto cleanup; 2462 } 2463 } 2464 /* now copy the property sets */ 2465 Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB); 2466 if(!NT_SUCCESS(Status)) 2467 goto cleanup; 2468 } 2469 2470 /* store result */ 2471 *AutomationTableAB = Table; 2472 2473 return Status; 2474 2475 2476 cleanup: 2477 2478 if (Table) 2479 { 2480 if (Table->PropertySets) 2481 { 2482 /* clean property sets */ 2483 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE))) 2484 FreeItem((PVOID)Table->PropertySets); 2485 } 2486 2487 if (Table->MethodSets) 2488 { 2489 /* clean property sets */ 2490 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE))) 2491 FreeItem((PVOID)Table->MethodSets); 2492 } 2493 2494 if (Table->EventSets) 2495 { 2496 /* clean property sets */ 2497 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE))) 2498 FreeItem((PVOID)Table->EventSets); 2499 } 2500 2501 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE))) 2502 FreeItem(Table); 2503 } 2504 2505 return STATUS_INSUFFICIENT_RESOURCES; 2506 } 2507 2508 /* 2509 @unimplemented 2510 */ 2511 KSDDKAPI 2512 PUNKNOWN 2513 NTAPI 2514 KsRegisterAggregatedClientUnknown( 2515 IN PVOID Object, 2516 IN PUNKNOWN ClientUnknown) 2517 { 2518 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 2519 2520 /* sanity check */ 2521 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 2522 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); 2523 2524 if (BasicHeader->ClientAggregate) 2525 { 2526 /* release existing aggregate */ 2527 BasicHeader->ClientAggregate->lpVtbl->Release(BasicHeader->ClientAggregate); 2528 } 2529 2530 /* increment reference count */ 2531 ClientUnknown->lpVtbl->AddRef(ClientUnknown); 2532 2533 /* store client aggregate */ 2534 BasicHeader->ClientAggregate = ClientUnknown; 2535 2536 /* return objects outer unknown */ 2537 return BasicHeader->OuterUnknown; 2538 } 2539 2540 /* 2541 @unimplemented 2542 */ 2543 NTSTATUS 2544 NTAPI 2545 KsRegisterFilterWithNoKSPins( 2546 IN PDEVICE_OBJECT DeviceObject, 2547 IN const GUID* InterfaceClassGUID, 2548 IN ULONG PinCount, 2549 IN BOOL* PinDirection, 2550 IN KSPIN_MEDIUM* MediumList, 2551 IN GUID* CategoryList OPTIONAL) 2552 { 2553 ULONG Size, Index; 2554 NTSTATUS Status; 2555 PWSTR SymbolicLinkList; 2556 //PUCHAR Buffer; 2557 HANDLE hKey; 2558 UNICODE_STRING InterfaceString; 2559 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData"); 2560 2561 if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList) 2562 { 2563 /* all these parameters are required */ 2564 return STATUS_INVALID_PARAMETER; 2565 } 2566 2567 /* calculate filter data value size */ 2568 Size = PinCount * sizeof(KSPIN_MEDIUM); 2569 if (CategoryList) 2570 { 2571 /* add category list */ 2572 Size += PinCount * sizeof(GUID); 2573 } 2574 2575 /* FIXME generate filter data blob */ 2576 UNIMPLEMENTED; 2577 2578 /* get symbolic link list */ 2579 Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList); 2580 if (NT_SUCCESS(Status)) 2581 { 2582 /* initialize first symbolic link */ 2583 RtlInitUnicodeString(&InterfaceString, SymbolicLinkList); 2584 2585 /* open first device interface registry key */ 2586 Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey); 2587 2588 if (NT_SUCCESS(Status)) 2589 { 2590 /* write filter data */ 2591 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size); 2592 2593 /* close the key */ 2594 ZwClose(hKey); 2595 } 2596 2597 if (PinCount) 2598 { 2599 /* update medium cache */ 2600 for(Index = 0; Index < PinCount; Index++) 2601 { 2602 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]); 2603 } 2604 } 2605 2606 /* free the symbolic link list */ 2607 FreeItem(SymbolicLinkList); 2608 } 2609 2610 return Status; 2611 } 2612