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