1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/api.cpp 5 * PURPOSE: Port api functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 NTSTATUS 15 NTAPI 16 KsoDispatchCreateWithGenericFactory( 17 LONG Unknown, 18 PIRP Irp) 19 { 20 UNIMPLEMENTED; 21 return STATUS_NOT_IMPLEMENTED; 22 } 23 24 IIrpTarget * 25 NTAPI 26 KsoGetIrpTargetFromFileObject( 27 PFILE_OBJECT FileObject) 28 { 29 PC_ASSERT(FileObject); 30 31 // IrpTarget is stored in FsContext 32 return (IIrpTarget*)FileObject->FsContext; 33 } 34 35 IIrpTarget * 36 NTAPI 37 KsoGetIrpTargetFromIrp( 38 PIRP Irp) 39 { 40 PIO_STACK_LOCATION IoStack; 41 42 // get current irp stack location 43 IoStack = IoGetCurrentIrpStackLocation(Irp); 44 45 // IIrpTarget is stored in Context member 46 return (IIrpTarget*)IoStack->FileObject->FsContext; 47 } 48 49 NTSTATUS 50 NTAPI 51 PcHandleEnableEventWithTable( 52 IN PIRP Irp, 53 IN PSUBDEVICE_DESCRIPTOR Descriptor) 54 { 55 // store descriptor 56 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor; 57 58 // FIXME seh probing 59 return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL); 60 } 61 62 NTSTATUS 63 NTAPI 64 PcHandleDisableEventWithTable( 65 IN PIRP Irp, 66 IN PSUBDEVICE_DESCRIPTOR Descriptor) 67 { 68 // store descriptor 69 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor; 70 71 // FIXME seh probing 72 73 return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock); 74 } 75 76 NTSTATUS 77 NTAPI 78 PcHandlePropertyWithTable( 79 IN PIRP Irp, 80 IN ULONG PropertySetCount, 81 IN PKSPROPERTY_SET PropertySet, 82 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor) 83 { 84 PIO_STACK_LOCATION IoStack; 85 86 // get current irp stack location 87 IoStack = IoGetCurrentIrpStackLocation(Irp); 88 89 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY)) 90 { 91 // certainly an invalid request 92 return STATUS_INVALID_PARAMETER; 93 } 94 95 // store device descriptor 96 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor; 97 98 // then try KsPropertyHandler 99 return KsPropertyHandler(Irp, PropertySetCount, PropertySet); 100 } 101 102 VOID 103 NTAPI 104 PcAcquireFormatResources( 105 LONG Unknown, 106 LONG Unknown2, 107 LONG Unknown3, 108 LONG Unknown4) 109 { 110 UNIMPLEMENTED; 111 } 112 113 NTSTATUS 114 PcAddToEventTable( 115 PVOID Ptr, 116 LONG Unknown2, 117 ULONG Length, 118 LONG Unknown3, 119 LONG Unknown4, 120 LONG Unknown5, 121 LONG Unknown6, 122 LONG Unknown7) 123 { 124 UNIMPLEMENTED; 125 return STATUS_NOT_IMPLEMENTED; 126 } 127 128 NTSTATUS 129 NTAPI 130 PropertyItemDispatch( 131 IN PIRP Irp, 132 IN PKSIDENTIFIER Request, 133 IN OUT PVOID Data) 134 { 135 PPCPROPERTY_REQUEST PropertyRequest; 136 PSUBDEVICE_DESCRIPTOR Descriptor; 137 PKSPROPERTY Property; 138 PPCNODE_DESCRIPTOR NodeDescriptor; 139 PKSNODEPROPERTY NodeProperty; 140 PKSPROPERTY_SET PropertySet; 141 PPCPROPERTY_ITEM PropertyItem; 142 PPCAUTOMATION_TABLE NodeAutomation; 143 PIO_STACK_LOCATION IoStack; 144 ULONG InstanceSize, ValueSize, Index; 145 PVOID Instance; 146 NTSTATUS Status; 147 148 // allocate a property request 149 PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS); 150 if (!PropertyRequest) 151 return STATUS_INSUFFICIENT_RESOURCES; 152 153 // grab device descriptor 154 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 155 156 // get current irp stack 157 IoStack = IoGetCurrentIrpStackLocation(Irp); 158 159 // get input property request 160 Property = (PKSPROPERTY)Request; 161 162 // get property set 163 PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp); 164 165 // sanity check 166 PC_ASSERT(Descriptor); 167 PC_ASSERT(Descriptor->UnknownMiniport); 168 169 // get instance / value size 170 InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength; 171 Instance = Request; 172 ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength; 173 174 // initialize property request 175 PropertyRequest->MajorTarget = Descriptor->UnknownMiniport; 176 PropertyRequest->MinorTarget = Descriptor->UnknownStream; 177 PropertyRequest->Irp = Irp; 178 PropertyRequest->Verb = Property->Flags; 179 180 // check if this is filter / pin property request 181 if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY)) 182 { 183 // adjust input buffer size 184 InstanceSize -= sizeof(KSPROPERTY); 185 Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY)); 186 187 // filter / pin property request dont use node field 188 PropertyRequest->Node = MAXULONG; 189 } 190 else if (InstanceSize >= sizeof(KSNODEPROPERTY)) 191 { 192 // request is for a node 193 InstanceSize -= sizeof(KSNODEPROPERTY); 194 Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY)); 195 196 // cast node property request 197 NodeProperty = (PKSNODEPROPERTY)Request; 198 199 // store node id 200 PropertyRequest->Node = NodeProperty->NodeId; 201 } 202 else 203 { 204 // invalid buffer size 205 FreeItem(PropertyRequest, TAG_PORTCLASS); 206 return STATUS_INVALID_BUFFER_SIZE; 207 } 208 209 // store instance size 210 PropertyRequest->InstanceSize = InstanceSize; 211 PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL); 212 213 // store value size 214 PropertyRequest->ValueSize = ValueSize; 215 PropertyRequest->Value = Data; 216 217 // now scan the property set for the attached property set item stored in Relations member 218 if (PropertySet) 219 { 220 // sanity check 221 PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set)); 222 223 for(Index = 0; Index < PropertySet->PropertiesCount; Index++) 224 { 225 // check if they got the same property id 226 if (PropertySet->PropertyItem[Index].PropertyId == Property->Id) 227 { 228 // found item 229 PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations; 230 231 // done 232 break; 233 } 234 } 235 } 236 237 // check if there has been a property set item attached 238 if (!PropertyRequest->PropertyItem) 239 { 240 // is topology node id valid 241 if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount) 242 { 243 // get node descriptor 244 NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize); 245 246 // get node automation table 247 NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable; 248 249 // has it got a automation table 250 if (NodeAutomation) 251 { 252 // now scan the properties and check if it supports this request 253 PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties; 254 for(Index = 0; Index < NodeAutomation->PropertyCount; Index++) 255 { 256 // are they same property 257 if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set)) 258 { 259 if (PropertyItem->Id == Property->Id) 260 { 261 // found match 262 PropertyRequest->PropertyItem = PropertyItem; 263 DPRINT("Using property item %p\n", PropertyItem); 264 // done 265 break; 266 } 267 } 268 269 // move to next property item 270 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize); 271 } 272 } 273 } 274 } 275 276 if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler) 277 { 278 // now call the handler 279 UNICODE_STRING GuidBuffer; 280 RtlStringFromGUID(Property->Set, &GuidBuffer); 281 DPRINT("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p PropertyItemFlags %lx PropertyItemId %lu\n", 282 PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize, 283 PropertyRequest->PropertyItem->Handler, PropertyRequest, PropertyRequest->PropertyItem->Flags, PropertyRequest->PropertyItem->Id); 284 RtlFreeUnicodeString(&GuidBuffer); 285 Status = PropertyRequest->PropertyItem->Handler(PropertyRequest); 286 DPRINT("Status %lx ValueSize %lu Information %lu\n", Status, PropertyRequest->ValueSize, Irp->IoStatus.Information); 287 Irp->IoStatus.Information = PropertyRequest->ValueSize; 288 289 if (Status != STATUS_PENDING) 290 { 291 // free property request 292 FreeItem(PropertyRequest, TAG_PORTCLASS); 293 } 294 } 295 else 296 { 297 FreeItem(PropertyRequest, TAG_PORTCLASS); 298 Status = STATUS_NOT_FOUND; 299 } 300 301 /* done */ 302 return Status; 303 } 304 305 NTSTATUS 306 PcAddToPropertyTable( 307 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor, 308 IN PPCPROPERTY_ITEM PropertyItem, 309 IN ULONG bNode) 310 { 311 ULONG bFound = FALSE; 312 ULONG Index, PropertySetIndex, PropertySetItemIndex; 313 PKSPROPERTY_SET NewPropertySet; 314 PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem; 315 LPGUID Guid; 316 //UNICODE_STRING GuidBuffer; 317 318 ASSERT(PropertyItem->Set); 319 // RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer); 320 // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags); 321 322 //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount); 323 // first step check if the property set is present already 324 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++) 325 { 326 327 //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer); 328 //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount); 329 if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set)) 330 { 331 // property set is already present 332 bFound = TRUE; 333 PropertySetIndex = Index; 334 335 // break out 336 break; 337 } 338 } 339 340 // is the property set present 341 if (!bFound) 342 { 343 // need to allocate a property set 344 NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS); 345 if (!NewPropertySet) 346 { 347 // out of memory 348 return STATUS_INSUFFICIENT_RESOURCES; 349 } 350 351 // need to allocate property set guid 352 Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS); 353 if (!Guid) 354 { 355 // out of memory 356 FreeItem(NewPropertySet, TAG_PORTCLASS); 357 return STATUS_INSUFFICIENT_RESOURCES; 358 } 359 360 // are any existing property sets 361 if (SubDeviceDescriptor->FilterPropertySetCount) 362 { 363 // copy property sets 364 RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET)); 365 366 // release memory 367 FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS); 368 } 369 370 // store new property set descriptors 371 SubDeviceDescriptor->FilterPropertySet = NewPropertySet; 372 373 // store index 374 PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount; 375 376 // increment property set count 377 SubDeviceDescriptor->FilterPropertySetCount++; 378 379 // copy property guid 380 RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID)); 381 382 // initialize property set 383 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid; 384 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0; 385 } 386 387 // as the property set has been identified, now search for duplicate property set item entries 388 FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem; 389 bFound = FALSE; 390 391 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++) 392 { 393 // now search for an equal property set item 394 if (FilterPropertyItem->PropertyId == PropertyItem->Id) 395 { 396 // found existing property set item 397 bFound = TRUE; 398 PropertySetItemIndex = Index; 399 break; 400 } 401 402 // move to next entry 403 FilterPropertyItem++; 404 } 405 406 if (!bFound) 407 { 408 // need to allocate memory for new property set item 409 NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS); 410 if (!NewFilterPropertyItem) 411 { 412 // out of memory 413 return STATUS_INSUFFICIENT_RESOURCES; 414 } 415 416 // are any existing property set items 417 if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount) 418 { 419 // copy property item sets 420 RtlMoveMemory(NewFilterPropertyItem, 421 (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, 422 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM)); 423 424 // release old descriptors 425 FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS); 426 } 427 428 // store new descriptor 429 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem; 430 431 // store index 432 PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; 433 434 // increment property item set count 435 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++; 436 437 // now initialize property item 438 FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex]; 439 FilterPropertyItem->PropertyId = PropertyItem->Id; 440 FilterPropertyItem->MinProperty = sizeof(KSPROPERTY); 441 FilterPropertyItem->MinData = 0; 442 443 // are any set operations supported 444 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET) 445 { 446 // setup handler 447 FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch; 448 } 449 450 // are set operation supported 451 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET) 452 { 453 // setup handler 454 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch; 455 } 456 457 // are get operations supported 458 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET) 459 { 460 // setup handler 461 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch; 462 } 463 464 // are basic support operations supported 465 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT) 466 { 467 // setup handler 468 FilterPropertyItem->SupportHandler = PropertyItemDispatch; 469 } 470 471 if (!bNode) 472 { 473 // store property item in relations 474 // only store property item of filter properties / pin properties 475 // because filter & pin properties do not require a specific context 476 // on the other hand node properties are specifically bound to a node 477 478 FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem; 479 } 480 } 481 else 482 { 483 // property set item handler already present 484 485 if (bNode) 486 { 487 // filter & pin properties should not be exposed on a node 488 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL); 489 } 490 else 491 { 492 // node properties should not be exposed on a filter & pin 493 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL); 494 } 495 } 496 497 // done 498 return STATUS_SUCCESS; 499 } 500 501 NTSTATUS 502 PcCaptureFormat( 503 LONG Unknown, 504 LONG Unknown2, 505 LONG Unknown3, 506 LONG Unknown4) 507 { 508 UNIMPLEMENTED; 509 return STATUS_NOT_IMPLEMENTED; 510 } 511 512 VOID 513 DumpAutomationTable( 514 IN PPCAUTOMATION_TABLE AutomationTable, 515 IN LPCWSTR DebugPrefix, 516 IN LPCWSTR DebugIndentation) 517 { 518 PPCPROPERTY_ITEM PropertyItem; 519 PPCEVENT_ITEM EventItem; 520 PPCMETHOD_ITEM MethodItem; 521 ULONG Index; 522 UNICODE_STRING GuidString; 523 524 if (!AutomationTable) 525 { 526 // no table 527 return; 528 } 529 530 DPRINT("=====================================================================\n"); 531 DPRINT("%S%S AutomationTable %p\n", DebugIndentation, DebugPrefix, AutomationTable); 532 DPRINT("%S%S PropertyCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->PropertyCount); 533 DPRINT("%S%S EventCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->EventCount); 534 DPRINT("%S%S MethodCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->MethodCount); 535 536 // print properties 537 if (AutomationTable->PropertyCount) 538 { 539 if (AutomationTable->PropertyItemSize >= sizeof(PCPROPERTY_ITEM)) 540 { 541 // get property item 542 PropertyItem = (PPCPROPERTY_ITEM)AutomationTable->Properties; 543 544 // sanity check 545 ASSERT(PropertyItem); 546 547 // display all properties associated 548 for(Index = 0; Index < AutomationTable->PropertyCount; Index++) 549 { 550 // convert to printable string 551 RtlStringFromGUID(*PropertyItem->Set, &GuidString); 552 DPRINT("%SPropertyItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, PropertyItem, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags); 553 RtlFreeUnicodeString(&GuidString); 554 // move to next item 555 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + AutomationTable->PropertyItemSize); 556 } 557 558 } 559 else 560 { 561 DPRINT1("DRIVER BUG: property item must be at least %lu but got %lu\n", sizeof(PCPROPERTY_ITEM), AutomationTable->PropertyItemSize); 562 } 563 } 564 565 // print events 566 if (AutomationTable->EventCount) 567 { 568 if (AutomationTable->EventItemSize >= sizeof(PCEVENT_ITEM)) 569 { 570 // get first event item 571 EventItem = (PPCEVENT_ITEM)AutomationTable->Events; 572 573 // sanity check 574 ASSERT(EventItem); 575 576 for(Index = 0; Index < AutomationTable->EventCount; Index++) 577 { 578 // convert to printable string 579 RtlStringFromGUID(*EventItem->Set, &GuidString); 580 DPRINT("%SEventItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, EventItem, GuidString.Buffer, EventItem->Id, EventItem->Flags); 581 RtlFreeUnicodeString(&GuidString); 582 583 // move to next item 584 EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + AutomationTable->EventItemSize); 585 } 586 } 587 else 588 { 589 DPRINT1("DRIVER BUG: event item must be at least %lu but got %lu\n", sizeof(PCEVENT_ITEM), AutomationTable->EventItemSize); 590 } 591 } 592 593 // print methods 594 if (AutomationTable->MethodCount) 595 { 596 if (AutomationTable->MethodItemSize >= sizeof(PCMETHOD_ITEM)) 597 { 598 // get first event item 599 MethodItem = (PPCMETHOD_ITEM)AutomationTable->Methods; 600 601 // sanity check 602 ASSERT(MethodItem); 603 604 for(Index = 0; Index < AutomationTable->MethodCount; Index++) 605 { 606 // convert to printable string 607 RtlStringFromGUID(*MethodItem->Set, &GuidString); 608 DPRINT("%SMethodItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, MethodItem, GuidString.Buffer, MethodItem->Id, MethodItem->Flags); 609 RtlFreeUnicodeString(&GuidString); 610 611 // move to next item 612 MethodItem = (PPCMETHOD_ITEM)((ULONG_PTR)MethodItem + AutomationTable->MethodItemSize); 613 } 614 615 } 616 else 617 { 618 DPRINT1("DRIVER BUG: method item must be at least %lu but got %lu\n", sizeof(PCEVENT_ITEM), AutomationTable->MethodItemSize); 619 } 620 } 621 DPRINT("=====================================================================\n"); 622 } 623 624 VOID 625 DumpFilterDescriptor( 626 IN PPCFILTER_DESCRIPTOR FilterDescription) 627 { 628 ULONG Index; 629 WCHAR Buffer[30]; 630 PPCPIN_DESCRIPTOR PinDescriptor; 631 PPCNODE_DESCRIPTOR NodeDescriptor; 632 633 DPRINT("======================\n"); 634 DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable); 635 DPRINT("PinCount %lu PinSize %lu StandardSize %lu\n", FilterDescription->PinCount, FilterDescription->PinSize, sizeof(PCPIN_DESCRIPTOR)); 636 DPRINT("NodeCount %lu NodeSize %lu StandardSize %lu\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR)); 637 638 // dump filter description table 639 DumpAutomationTable((PPCAUTOMATION_TABLE)FilterDescription->AutomationTable, L"Filter", L""); 640 641 if (FilterDescription->PinCount) 642 { 643 if (FilterDescription->PinSize >= sizeof(PCPIN_DESCRIPTOR)) 644 { 645 // get first pin 646 PinDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins; 647 648 // sanity check 649 ASSERT(PinDescriptor); 650 651 for(Index = 0; Index < FilterDescription->PinCount; Index++) 652 { 653 // print prefix 654 swprintf(Buffer, L"PinIndex %lu", Index); 655 656 // dump automation table 657 DumpAutomationTable((PPCAUTOMATION_TABLE)PinDescriptor->AutomationTable, Buffer, L" "); 658 659 // move to next pin descriptor 660 PinDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)PinDescriptor + FilterDescription->PinSize); 661 } 662 } 663 else 664 { 665 DPRINT1("DRIVER BUG: pin size smaller than minimum size\n"); 666 } 667 } 668 669 if (FilterDescription->Nodes) 670 { 671 if (FilterDescription->NodeSize >= sizeof(PCNODE_DESCRIPTOR)) 672 { 673 // get first descriptor 674 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes; 675 676 // sanity check 677 ASSERT(NodeDescriptor); 678 679 for(Index = 0; Index < FilterDescription->NodeCount; Index++) 680 { 681 // print prefix 682 swprintf(Buffer, L"NodeIndex %lu", Index); 683 684 // dump automation table 685 DumpAutomationTable((PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable, Buffer, L" "); 686 687 // move to next node descriptor 688 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize); 689 } 690 } 691 else 692 { 693 DPRINT1("DRIVER BUG: node size smaller than standard descriptor size\n"); 694 } 695 } 696 697 DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount); 698 699 if (FilterDescription->ConnectionCount) 700 { 701 DPRINT("------ Start of Nodes Connections ----------------\n"); 702 for(Index = 0; Index < FilterDescription->ConnectionCount; Index++) 703 { 704 DPRINT1("Index %ld FromPin %ld FromNode %ld -> ToPin %ld ToNode %ld\n", Index, 705 FilterDescription->Connections[Index].FromNodePin, 706 FilterDescription->Connections[Index].FromNode, 707 FilterDescription->Connections[Index].ToNodePin, 708 FilterDescription->Connections[Index].ToNode); 709 } 710 DPRINT("------ End of Nodes Connections----------------\n"); 711 } 712 DPRINT1("======================\n"); 713 } 714 715 NTSTATUS 716 NTAPI 717 PcCreateSubdeviceDescriptor( 718 OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor, 719 IN ULONG InterfaceCount, 720 IN GUID * InterfaceGuids, 721 IN ULONG IdentifierCount, 722 IN KSIDENTIFIER *Identifier, 723 IN ULONG FilterPropertiesCount, 724 IN KSPROPERTY_SET * FilterProperties, 725 IN ULONG Unknown1, 726 IN ULONG Unknown2, 727 IN ULONG PinPropertiesCount, 728 IN KSPROPERTY_SET * PinProperties, 729 IN ULONG EventSetCount, 730 IN KSEVENT_SET * EventSet, 731 IN PPCFILTER_DESCRIPTOR FilterDescription) 732 { 733 SUBDEVICE_DESCRIPTOR * Descriptor; 734 ULONG Index, SubIndex; 735 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 736 PPCPIN_DESCRIPTOR SrcDescriptor; 737 PPCNODE_DESCRIPTOR NodeDescriptor; 738 PPCPROPERTY_ITEM PropertyItem; 739 740 // allocate subdevice descriptor 741 Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS); 742 if (!Descriptor) 743 return STATUS_INSUFFICIENT_RESOURCES; 744 745 // initialize physical / symbolic link connection list 746 InitializeListHead(&Descriptor->SymbolicLinkList); 747 InitializeListHead(&Descriptor->PhysicalConnectionList); 748 749 //FIXME add driver category guids 750 Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS); 751 if (!Descriptor->Interfaces) 752 goto cleanup; 753 754 // copy interface guids 755 RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount); 756 Descriptor->InterfaceCount = InterfaceCount; 757 758 //DumpFilterDescriptor(FilterDescription); 759 760 // are any property sets supported by the portcls 761 if (FilterPropertiesCount) 762 { 763 // first allocate filter properties set 764 Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS); 765 if (! Descriptor->FilterPropertySet) 766 goto cleanup; 767 768 // now copy all filter property sets 769 Descriptor->FilterPropertySetCount = FilterPropertiesCount; 770 for(Index = 0; Index < FilterPropertiesCount; Index++) 771 { 772 // copy property set 773 RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET)); 774 775 if (Descriptor->FilterPropertySet[Index].PropertiesCount) 776 { 777 // copy property items to make sure they are dynamically allocated 778 Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS); 779 if (!Descriptor->FilterPropertySet[Index].PropertyItem) 780 { 781 // no memory 782 goto cleanup; 783 } 784 785 // copy filter property items 786 RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM)); 787 } 788 } 789 } 790 791 // now check if the filter descriptor supports filter properties 792 if (FilterDescription->AutomationTable) 793 { 794 // get first entry 795 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties; 796 797 // copy driver filter property sets 798 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++) 799 { 800 // add the property item 801 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE); 802 803 // check for success 804 if (Status != STATUS_SUCCESS) 805 { 806 // goto cleanup 807 goto cleanup; 808 } 809 810 // move to next entry 811 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize); 812 } 813 } 814 815 // check if the filter has pins 816 if (FilterDescription->PinCount) 817 { 818 // allocate pin factory descriptors 819 Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS); 820 if (!Descriptor->Factory.KsPinDescriptor) 821 goto cleanup; 822 823 // allocate pin instance info 824 Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS); 825 if (!Descriptor->Factory.Instances) 826 goto cleanup; 827 828 // initialize pin factory descriptor 829 Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount; 830 Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR); 831 832 // grab first entry 833 SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins; 834 835 // copy pin factories 836 for(Index = 0; Index < FilterDescription->PinCount; Index++) 837 { 838 // copy pin descriptor 839 RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR)); 840 841 // initialize pin factory instance data 842 Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0; 843 Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount; 844 Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount; 845 Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount; 846 847 // check if the descriptor has an automation table 848 if (SrcDescriptor->AutomationTable) 849 { 850 // it has, grab first entry 851 PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties; 852 853 // now add all supported property items 854 for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++) 855 { 856 // add the property item to the table 857 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE); 858 859 // check for success 860 if (Status != STATUS_SUCCESS) 861 { 862 // goto cleanup 863 goto cleanup; 864 } 865 866 // move to next entry 867 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize); 868 } 869 } 870 871 // move to next entry 872 SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize); 873 } 874 } 875 876 // allocate topology descriptor 877 Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS); 878 if (!Descriptor->Topology) 879 goto cleanup; 880 881 // are there any connections 882 if (FilterDescription->ConnectionCount) 883 { 884 // allocate connection descriptor 885 Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS); 886 if (!Descriptor->Topology->TopologyConnections) 887 goto cleanup; 888 889 // copy connection descriptor 890 RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR)); 891 892 // store connection count 893 Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount; 894 } 895 896 // does the filter have nodes 897 if (FilterDescription->NodeCount) 898 { 899 // allocate topology node types array 900 Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS); 901 if (!Descriptor->Topology->TopologyNodes) 902 goto cleanup; 903 904 // allocate topology node names array 905 Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS); 906 if (!Descriptor->Topology->TopologyNodesNames) 907 goto cleanup; 908 909 // grab first entry 910 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes; 911 912 // iterate all nodes and copy node types / names and node properties 913 for(Index = 0; Index < FilterDescription->NodeCount; Index++) 914 { 915 // does it have a type 916 if (NodeDescriptor->Type) 917 { 918 // copy node type 919 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID)); 920 } 921 922 // does it have a node name 923 if (NodeDescriptor->Name) 924 { 925 // copy node name 926 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID)); 927 } 928 929 // check if has an automation table 930 if (NodeDescriptor->AutomationTable) 931 { 932 // grab first entry 933 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties; 934 935 // copy all node properties into the global property set 936 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++) 937 { 938 // add to property set 939 Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE); 940 941 // check for success 942 if (Status != STATUS_SUCCESS) 943 { 944 // failed 945 goto cleanup; 946 } 947 948 // move to next property item 949 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize); 950 } 951 } 952 953 // move to next descriptor 954 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize); 955 } 956 957 // now store the topology node count 958 Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount; 959 } 960 961 // store descriptor 962 Descriptor->DeviceDescriptor = FilterDescription; 963 964 // store result 965 *OutSubdeviceDescriptor = Descriptor; 966 // done 967 return STATUS_SUCCESS; 968 969 cleanup: 970 if (Descriptor) 971 { 972 if (Descriptor->Interfaces) 973 FreeItem(Descriptor->Interfaces, TAG_PORTCLASS); 974 975 if (Descriptor->Factory.KsPinDescriptor) 976 FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS); 977 978 FreeItem(Descriptor, TAG_PORTCLASS); 979 } 980 return Status; 981 } 982 983 NTSTATUS 984 NTAPI 985 PcValidateConnectRequest( 986 IN PIRP Irp, 987 IN KSPIN_FACTORY * Factory, 988 OUT PKSPIN_CONNECT * Connect) 989 { 990 return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect); 991 } 992