1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/ksfilter/ks/connectivity.c 5 * PURPOSE: KS Pin functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 KSPIN_INTERFACE StandardPinInterface = 15 { 16 {STATIC_KSINTERFACESETID_Standard}, 17 KSINTERFACE_STANDARD_STREAMING, 18 0 19 }; 20 21 KSPIN_MEDIUM StandardPinMedium = 22 { 23 {STATIC_KSMEDIUMSETID_Standard}, 24 KSMEDIUM_TYPE_ANYINSTANCE, 25 0 26 }; 27 28 const GUID KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT = {0xf4aeb342, 0x0329, 0x4fdd, {0xa8, 0xfd, 0x4a, 0xff, 0x49, 0x26, 0xc9, 0x78}}; 29 30 /* 31 @implemented 32 */ 33 KSDDKAPI 34 NTSTATUS 35 NTAPI 36 KsCreatePin( 37 IN HANDLE FilterHandle, 38 IN PKSPIN_CONNECT Connect, 39 IN ACCESS_MASK DesiredAccess, 40 OUT PHANDLE ConnectionHandle) 41 { 42 UINT ConnectSize = sizeof(KSPIN_CONNECT); 43 44 PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1); 45 if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) || 46 Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX)) 47 { 48 ConnectSize += Format->DataFormat.FormatSize; 49 } 50 51 return KspCreateObjectType(FilterHandle, 52 KSSTRING_Pin, 53 (PVOID)Connect, 54 ConnectSize, 55 DesiredAccess, 56 ConnectionHandle); 57 } 58 59 NTSTATUS 60 KspValidateConnectRequest( 61 IN PIRP Irp, 62 IN ULONG DescriptorsCount, 63 IN PVOID Descriptors, 64 IN ULONG DescriptorSize, 65 OUT PKSPIN_CONNECT* Connect) 66 { 67 PKSPIN_CONNECT ConnectDetails; 68 PKSPIN_INTERFACE Interface; 69 PKSPIN_MEDIUM Medium; 70 ULONG Size; 71 NTSTATUS Status; 72 ULONG Index; 73 ULONG Count; 74 BOOLEAN Found; 75 PKSPIN_DESCRIPTOR Descriptor; 76 UNICODE_STRING GuidString2; 77 78 /* did the caller miss the connect parameter */ 79 if (!Connect) 80 return STATUS_INVALID_PARAMETER; 81 82 /* set create param size */ 83 Size = sizeof(KSPIN_CONNECT); 84 85 /* fetch create parameters */ 86 Status = KspCopyCreateRequest(Irp, 87 KSSTRING_Pin, 88 &Size, 89 (PVOID*)&ConnectDetails); 90 91 /* check for success */ 92 if (!NT_SUCCESS(Status)) 93 return Status; 94 95 /* is pin id out of bounds */ 96 if (ConnectDetails->PinId >= DescriptorsCount) 97 { 98 FreeItem(ConnectDetails); 99 return STATUS_INVALID_PARAMETER; 100 } 101 102 if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR)) 103 { 104 /* standard pin descriptor */ 105 Descriptor = (PKSPIN_DESCRIPTOR)((ULONG_PTR)Descriptors + sizeof(KSPIN_DESCRIPTOR) * ConnectDetails->PinId); 106 } 107 else 108 { 109 /* extended / variable pin descriptor */ 110 Descriptor = &((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + DescriptorSize * ConnectDetails->PinId))->PinDescriptor; 111 } 112 113 114 /* does the pin have interface details filled in */ 115 if (Descriptor->InterfacesCount && Descriptor->Interfaces) 116 { 117 /* use provided pin interface count */ 118 Count = Descriptor->InterfacesCount; 119 Interface = (PKSPIN_INTERFACE)Descriptor->Interfaces; 120 } 121 else 122 { 123 /* use standard pin interface */ 124 Count = 1; 125 Interface = &StandardPinInterface; 126 } 127 128 /* now check the interface */ 129 Found = FALSE; 130 Index = 0; 131 RtlStringFromGUID(&ConnectDetails->Interface.Set, &GuidString2); 132 do 133 { 134 UNICODE_STRING GuidString; 135 RtlStringFromGUID(&Interface[Index].Set, &GuidString); 136 137 DPRINT("Driver Interface %S Id %u\n", GuidString.Buffer, Interface[Index].Id); 138 DPRINT("Connect Interface %S Id %u\n", GuidString2.Buffer, ConnectDetails->Interface.Id); 139 140 RtlFreeUnicodeString(&GuidString); 141 142 if (IsEqualGUIDAligned(&Interface[Index].Set, &ConnectDetails->Interface.Set) && 143 Interface[Index].Id == ConnectDetails->Interface.Id) 144 { 145 /* found a matching interface */ 146 Found = TRUE; 147 break; 148 } 149 /* iterate to next interface */ 150 Index++; 151 }while(Index < Count); 152 RtlFreeUnicodeString(&GuidString2); 153 154 if (!Found) 155 { 156 /* pin doesnt support this interface */ 157 FreeItem(ConnectDetails); 158 return STATUS_NO_MATCH; 159 } 160 161 /* does the pin have medium details filled in */ 162 if (Descriptor->MediumsCount && Descriptor->Mediums) 163 { 164 /* use provided pin interface count */ 165 Count = Descriptor->MediumsCount; 166 Medium = (PKSPIN_MEDIUM)Descriptor->Mediums; 167 } 168 else 169 { 170 /* use standard pin interface */ 171 Count = 1; 172 Medium = &StandardPinMedium; 173 } 174 175 /* now check the interface */ 176 Found = FALSE; 177 Index = 0; 178 RtlStringFromGUID(&ConnectDetails->Medium.Set, &GuidString2); 179 do 180 { 181 UNICODE_STRING GuidString; 182 RtlStringFromGUID(&Medium[Index].Set, &GuidString); 183 184 DPRINT("Driver Medium %S Id %u\n", GuidString.Buffer, Medium[Index].Id); 185 DPRINT("Connect Medium %S Id %u\n", GuidString2.Buffer, ConnectDetails->Medium.Id); 186 187 RtlFreeUnicodeString(&GuidString); 188 189 if (IsEqualGUIDAligned(&Medium[Index].Set, &ConnectDetails->Medium.Set) && 190 Medium[Index].Id == ConnectDetails->Medium.Id) 191 { 192 /* found a matching interface */ 193 Found = TRUE; 194 break; 195 } 196 197 /* iterate to next medium */ 198 Index++; 199 }while(Index < Count); 200 RtlFreeUnicodeString(&GuidString2); 201 202 if (!Found) 203 { 204 /* pin doesnt support this medium */ 205 FreeItem(ConnectDetails); 206 return STATUS_NO_MATCH; 207 } 208 209 /// FIXME 210 /// implement format checking 211 212 *Connect = ConnectDetails; 213 return STATUS_SUCCESS; 214 } 215 216 /* 217 @implemented 218 */ 219 KSDDKAPI 220 NTSTATUS 221 NTAPI 222 KsValidateConnectRequest( 223 IN PIRP Irp, 224 IN ULONG DescriptorsCount, 225 IN KSPIN_DESCRIPTOR* Descriptor, 226 OUT PKSPIN_CONNECT* Connect) 227 { 228 return KspValidateConnectRequest(Irp, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR), Connect); 229 } 230 231 NTSTATUS 232 KspReadMediaCategory( 233 IN LPGUID Category, 234 PKEY_VALUE_PARTIAL_INFORMATION *OutInformation) 235 { 236 UNICODE_STRING MediaPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\"); 237 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name"); 238 UNICODE_STRING GuidString, Path; 239 NTSTATUS Status; 240 OBJECT_ATTRIBUTES ObjectAttributes; 241 HANDLE hKey; 242 ULONG Size; 243 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; 244 245 /* convert the guid to string */ 246 Status = RtlStringFromGUID(Category, &GuidString); 247 if (!NT_SUCCESS(Status)) 248 return Status; 249 250 /* allocate buffer for the registry key */ 251 Path.Length = 0; 252 Path.MaximumLength = MediaPath.MaximumLength + GuidString.MaximumLength; 253 Path.Buffer = AllocateItem(NonPagedPool, Path.MaximumLength); 254 if (!Path.Buffer) 255 { 256 /* not enough memory */ 257 RtlFreeUnicodeString(&GuidString); 258 return STATUS_INSUFFICIENT_RESOURCES; 259 } 260 261 RtlAppendUnicodeStringToString(&Path, &MediaPath); 262 RtlAppendUnicodeStringToString(&Path, &GuidString); 263 264 /* free guid string */ 265 RtlFreeUnicodeString(&GuidString); 266 267 /* initialize object attributes */ 268 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_CASE_INSENSITIVE, NULL, NULL); 269 270 /* open the key */ 271 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes); 272 273 DPRINT("ZwOpenKey() status 0x%08lx %wZ\n", Status, &Path); 274 275 /* free path buffer */ 276 FreeItem(Path.Buffer); 277 278 /* check for success */ 279 if (!NT_SUCCESS(Status)) 280 { 281 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status); 282 return Status; 283 } 284 285 /* query the name size */ 286 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size); 287 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) 288 { 289 /* failed to query for name key */ 290 ZwClose(hKey); 291 return Status; 292 } 293 294 /* allocate buffer to read key info */ 295 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) AllocateItem(NonPagedPool, Size); 296 if (!KeyInfo) 297 { 298 /* not enough memory */ 299 ZwClose(hKey); 300 return STATUS_INSUFFICIENT_RESOURCES; 301 } 302 303 /* now read the info */ 304 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size); 305 306 /* close the key */ 307 ZwClose(hKey); 308 309 if (!NT_SUCCESS(Status)) 310 { 311 /* failed to read key */ 312 FreeItem(KeyInfo); 313 return Status; 314 } 315 316 /* store key information */ 317 *OutInformation = KeyInfo; 318 return Status; 319 } 320 321 KSDDKAPI 322 NTSTATUS 323 NTAPI 324 KspPinPropertyHandler( 325 IN PIRP Irp, 326 IN PKSPROPERTY Property, 327 IN OUT PVOID Data, 328 IN ULONG DescriptorsCount, 329 IN const KSPIN_DESCRIPTOR* Descriptors, 330 IN ULONG DescriptorSize) 331 { 332 KSP_PIN * Pin; 333 KSMULTIPLE_ITEM * Item; 334 PIO_STACK_LOCATION IoStack; 335 ULONG Size, Index; 336 PVOID Buffer; 337 PKSDATARANGE_AUDIO *WaveFormatOut; 338 PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn; 339 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; 340 const KSPIN_DESCRIPTOR *Descriptor; 341 NTSTATUS Status = STATUS_NOT_SUPPORTED; 342 ULONG Count; 343 const PKSDATARANGE* DataRanges; 344 LPGUID Guid; 345 346 IoStack = IoGetCurrentIrpStackLocation(Irp); 347 Buffer = Data; 348 349 //DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptor, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); 350 351 /* convert to PKSP_PIN */ 352 Pin = (KSP_PIN*)Property; 353 354 if (Property->Id != KSPROPERTY_PIN_CTYPES) 355 { 356 if (Pin->PinId >= DescriptorsCount) 357 { 358 /* invalid parameter */ 359 return STATUS_INVALID_PARAMETER; 360 } 361 } 362 else 363 { 364 (*(PULONG)Buffer) = DescriptorsCount; 365 Irp->IoStatus.Information = sizeof(ULONG); 366 return STATUS_SUCCESS; 367 } 368 369 370 if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR)) 371 { 372 /* it is simple pin descriptor */ 373 Descriptor = &Descriptors[Pin->PinId]; 374 } 375 else 376 { 377 /* get offset to pin descriptor */ 378 Descriptor = &(((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + Pin->PinId * DescriptorSize))->PinDescriptor); 379 } 380 381 switch(Property->Id) 382 { 383 case KSPROPERTY_PIN_DATAFLOW: 384 385 Size = sizeof(KSPIN_DATAFLOW); 386 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) 387 { 388 Irp->IoStatus.Information = Size; 389 Status = STATUS_BUFFER_TOO_SMALL; 390 break; 391 } 392 393 *((KSPIN_DATAFLOW*)Buffer) = Descriptor->DataFlow; 394 Irp->IoStatus.Information = sizeof(KSPIN_DATAFLOW); 395 Status = STATUS_SUCCESS; 396 break; 397 398 case KSPROPERTY_PIN_DATARANGES: 399 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: 400 401 Size = sizeof(KSMULTIPLE_ITEM); 402 DPRINT("Id %lu PinId %lu DataRangesCount %lu ConstrainedDataRangesCount %lu\n", Property->Id, Pin->PinId, Descriptor->DataRangesCount, Descriptor->ConstrainedDataRangesCount); 403 404 if (Property->Id == KSPROPERTY_PIN_DATARANGES || Descriptor->ConstrainedDataRangesCount == 0) 405 { 406 DataRanges = Descriptor->DataRanges; 407 Count = Descriptor->DataRangesCount; 408 } 409 else 410 { 411 DataRanges = Descriptor->ConstrainedDataRanges; 412 Count = Descriptor->ConstrainedDataRangesCount; 413 } 414 415 for (Index = 0; Index < Count; Index++) 416 { 417 Size += ((DataRanges[Index]->FormatSize + 0x7) & ~0x7); 418 } 419 420 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0) 421 { 422 /* buffer too small */ 423 Irp->IoStatus.Information = Size; 424 Status = STATUS_BUFFER_OVERFLOW; 425 break; 426 } 427 428 Item = (KSMULTIPLE_ITEM*)Buffer; 429 430 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG)) 431 { 432 /* store the result size */ 433 Item->Size = Size; 434 Irp->IoStatus.Information = sizeof(ULONG); 435 Status = STATUS_SUCCESS; 436 break; 437 } 438 439 /* store descriptor size */ 440 Item->Size = Size; 441 Item->Count = Count; 442 443 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM)) 444 { 445 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM); 446 Status = STATUS_SUCCESS; 447 break; 448 } 449 450 /* now copy all dataranges */ 451 Data = (PUCHAR)(Item +1); 452 453 /* alignment assert */ 454 ASSERT(((ULONG_PTR)Data & 0x7) == 0); 455 456 for (Index = 0; Index < Count; Index++) 457 { 458 UNICODE_STRING GuidString; 459 /* convert the guid to string */ 460 RtlStringFromGUID(&DataRanges[Index]->MajorFormat, &GuidString); 461 DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer); 462 RtlStringFromGUID(&DataRanges[Index]->SubFormat, &GuidString); 463 DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer); 464 RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString); 465 DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer); 466 RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString); 467 DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index, 468 DataRanges[Index]->FormatSize, DataRanges[Index]->Flags, DataRanges[Index]->SampleSize, DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT)); 469 470 RtlMoveMemory(Data, DataRanges[Index], DataRanges[Index]->FormatSize); 471 Data = ((PUCHAR)Data + DataRanges[Index]->FormatSize); 472 /* alignment assert */ 473 ASSERT(((ULONG_PTR)Data & 0x7) == 0); 474 Data = (PVOID)(((ULONG_PTR)Data + 0x7) & ~0x7); 475 } 476 477 Status = STATUS_SUCCESS; 478 Irp->IoStatus.Information = Size; 479 break; 480 case KSPROPERTY_PIN_INTERFACES: 481 482 if (Descriptor->Interfaces) 483 { 484 /* use mediums provided by driver */ 485 return KsHandleSizedListQuery(Irp, Descriptor->InterfacesCount, sizeof(KSPIN_MEDIUM), Descriptor->Interfaces); 486 } 487 else 488 { 489 /* use standard medium */ 490 return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_INTERFACE), &StandardPinInterface); 491 } 492 break; 493 494 case KSPROPERTY_PIN_MEDIUMS: 495 496 if (Descriptor->MediumsCount) 497 { 498 /* use mediums provided by driver */ 499 return KsHandleSizedListQuery(Irp, Descriptor->MediumsCount, sizeof(KSPIN_MEDIUM), Descriptor->Mediums); 500 } 501 else 502 { 503 /* use standard medium */ 504 return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_MEDIUM), &StandardPinMedium); 505 } 506 break; 507 508 case KSPROPERTY_PIN_COMMUNICATION: 509 510 Size = sizeof(KSPIN_COMMUNICATION); 511 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) 512 { 513 Irp->IoStatus.Information = Size; 514 Status = STATUS_BUFFER_TOO_SMALL; 515 break; 516 } 517 518 *((KSPIN_COMMUNICATION*)Buffer) = Descriptor->Communication; 519 520 Status = STATUS_SUCCESS; 521 Irp->IoStatus.Information = Size; 522 break; 523 524 case KSPROPERTY_PIN_CATEGORY: 525 526 if (!Descriptor->Category) 527 { 528 /* no pin category */ 529 return STATUS_NOT_FOUND; 530 } 531 532 /* check size */ 533 Size = sizeof(GUID); 534 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) 535 { 536 /* buffer too small */ 537 Irp->IoStatus.Information = Size; 538 Status = STATUS_BUFFER_TOO_SMALL; 539 break; 540 } 541 542 /* copy category guid */ 543 RtlMoveMemory(Buffer, Descriptor->Category, sizeof(GUID)); 544 545 /* save result */ 546 Status = STATUS_SUCCESS; 547 Irp->IoStatus.Information = Size; 548 break; 549 550 case KSPROPERTY_PIN_NAME: 551 552 if (Descriptor->Name) 553 { 554 /* use pin name */ 555 Guid = (LPGUID)Descriptor->Name; 556 } 557 else 558 { 559 /* use pin category as fallback */ 560 Guid = (LPGUID)Descriptor->Category; 561 } 562 563 if (!Guid) 564 { 565 /* no friendly name available */ 566 return STATUS_NOT_FOUND; 567 } 568 569 /* read friendly name category name */ 570 Status = KspReadMediaCategory(Guid, &KeyInfo); 571 if (!NT_SUCCESS(Status)) 572 { 573 /* failed to read category */ 574 Irp->IoStatus.Information = 0; 575 break; 576 } 577 578 /* store required length */ 579 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR); 580 581 /* check if buffer is too small */ 582 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength) 583 { 584 /* buffer too small */ 585 Status = STATUS_BUFFER_OVERFLOW; 586 FreeItem(KeyInfo); 587 break; 588 } 589 590 /* copy result */ 591 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, &KeyInfo->Data, KeyInfo->DataLength); 592 593 /* null terminate name */ 594 ((LPWSTR)Irp->AssociatedIrp.SystemBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0'; 595 596 /* free key info */ 597 FreeItem(KeyInfo); 598 break; 599 case KSPROPERTY_PIN_PROPOSEDATAFORMAT: 600 Size = sizeof(KSDATAFORMAT); 601 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) 602 { 603 Irp->IoStatus.Information = Size; 604 Status = STATUS_BUFFER_TOO_SMALL; 605 break; 606 } 607 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX)) 608 { 609 UNIMPLEMENTED; 610 Status = STATUS_NOT_IMPLEMENTED; 611 Irp->IoStatus.Information = 0; 612 break; 613 } 614 615 WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer; 616 if (!Descriptor->DataRanges || !Descriptor->DataRangesCount) 617 { 618 Status = STATUS_UNSUCCESSFUL; 619 Irp->IoStatus.Information = 0; 620 break; 621 } 622 WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor->DataRanges; 623 for(Index = 0; Index < Descriptor->DataRangesCount; Index++) 624 { 625 if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) 626 { 627 UNIMPLEMENTED; 628 continue; 629 } 630 631 if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec || 632 WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec || 633 WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample || 634 WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample || 635 WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels) 636 { 637 Irp->IoStatus.Status = STATUS_NO_MATCH; 638 Irp->IoStatus.Information = 0; 639 return STATUS_NO_MATCH; 640 } 641 else 642 { 643 Irp->IoStatus.Status = STATUS_SUCCESS; 644 Irp->IoStatus.Information = 0; 645 return STATUS_SUCCESS; 646 } 647 } 648 Status = STATUS_NO_MATCH; 649 Irp->IoStatus.Information = 0; 650 break; 651 default: 652 DPRINT1("Unhandled property request %x\n", Property->Id); 653 Status = STATUS_NOT_IMPLEMENTED; 654 Irp->IoStatus.Information = 0; 655 } 656 657 return Status; 658 } 659 660 /* 661 @implemented 662 */ 663 KSDDKAPI 664 NTSTATUS 665 NTAPI 666 KsPinPropertyHandler( 667 IN PIRP Irp, 668 IN PKSPROPERTY Property, 669 IN OUT PVOID Data, 670 IN ULONG DescriptorsCount, 671 IN const KSPIN_DESCRIPTOR* Descriptor) 672 { 673 return KspPinPropertyHandler(Irp, Property, Data, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR)); 674 } 675 676 /* 677 @unimplemented 678 */ 679 KSDDKAPI NTSTATUS NTAPI 680 KsPinDataIntersectionEx( 681 IN PIRP Irp, 682 IN PKSP_PIN Pin, 683 OUT PVOID Data, 684 IN ULONG DescriptorsCount, 685 IN const KSPIN_DESCRIPTOR* Descriptor, 686 IN ULONG DescriptorSize, 687 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL, 688 IN PVOID HandlerContext OPTIONAL) 689 { 690 UNIMPLEMENTED; 691 return STATUS_UNSUCCESSFUL; 692 } 693 694 /* 695 @implemented 696 */ 697 KSDDKAPI 698 NTSTATUS 699 NTAPI 700 KsPinDataIntersection( 701 IN PIRP Irp, 702 IN PKSP_PIN Pin, 703 OUT PVOID Data, 704 IN ULONG DescriptorsCount, 705 IN const KSPIN_DESCRIPTOR* Descriptor, 706 IN PFNKSINTERSECTHANDLER IntersectHandler) 707 { 708 KSMULTIPLE_ITEM * Item; 709 KSDATARANGE * DataRange; 710 PIO_STACK_LOCATION IoStack; 711 ULONG Size; 712 ULONG Index; 713 NTSTATUS Status; 714 715 /* get current irp stack location */ 716 IoStack = IoGetCurrentIrpStackLocation(Irp); 717 718 /* calculate minimum data size */ 719 Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE); 720 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size) 721 { 722 /* buffer too small */ 723 Irp->IoStatus.Information = Size; 724 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 725 return STATUS_BUFFER_TOO_SMALL; 726 } 727 /* is pin id out of bounds */ 728 if (Pin->PinId >= DescriptorsCount) 729 { 730 /* it is */ 731 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 732 Irp->IoStatus.Information = 0; 733 return STATUS_INVALID_PARAMETER; 734 } 735 736 /* get start item */ 737 Item = (KSMULTIPLE_ITEM*)(Pin + 1); 738 /* get first data range */ 739 DataRange = (KSDATARANGE*)(Item + 1); 740 /* iterate through all data ranges */ 741 for(Index = 0; Index < Item->Count; Index++, DataRange++) 742 { 743 /* call intersect handler */ 744 Status = IntersectHandler(Irp, Pin, DataRange, Data); 745 if (NT_SUCCESS(Status)) 746 { 747 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize) 748 { 749 /* buffer is too small */ 750 Irp->IoStatus.Information = DataRange->FormatSize; 751 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 752 return STATUS_BUFFER_TOO_SMALL; 753 } 754 RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE)); 755 Irp->IoStatus.Information = sizeof(KSDATARANGE); 756 Irp->IoStatus.Status = STATUS_SUCCESS; 757 return STATUS_SUCCESS; 758 } 759 760 } 761 762 Irp->IoStatus.Information = 0; 763 Irp->IoStatus.Status = STATUS_NO_MATCH; 764 return STATUS_NO_MATCH; 765 } 766 767 /* 768 @implemented 769 */ 770 771 KSDDKAPI 772 NTSTATUS 773 NTAPI 774 KsHandleSizedListQuery( 775 IN PIRP Irp, 776 IN ULONG DataItemsCount, 777 IN ULONG DataItemSize, 778 IN const VOID* DataItems) 779 { 780 ULONG Size; 781 PIO_STACK_LOCATION IoStack; 782 PKSMULTIPLE_ITEM Item; 783 784 /* get current irp stack location */ 785 IoStack = IoGetCurrentIrpStackLocation(Irp); 786 787 /* calculate size */ 788 Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM); 789 790 /* get multiple item */ 791 Item = (PKSMULTIPLE_ITEM)Irp->AssociatedIrp.SystemBuffer; 792 793 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0) 794 { 795 /* buffer too small */ 796 Irp->IoStatus.Information = Size; 797 798 return STATUS_BUFFER_OVERFLOW; 799 } 800 801 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG)) 802 { 803 /* store just the size */ 804 Item->Size = Size; 805 Irp->IoStatus.Information = sizeof(ULONG); 806 807 return STATUS_SUCCESS; 808 } 809 810 811 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM)) 812 { 813 /* buffer too small */ 814 return STATUS_BUFFER_TOO_SMALL; 815 } 816 817 Item->Count = DataItemsCount; 818 Item->Size = DataItemSize; 819 820 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM)) 821 { 822 /* buffer can only hold the length descriptor */ 823 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM); 824 return STATUS_SUCCESS; 825 } 826 827 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= Size) 828 { 829 /* copy items */ 830 RtlMoveMemory((PVOID)(Item + 1), DataItems, DataItemSize * DataItemsCount); 831 /* store result */ 832 Irp->IoStatus.Information = Size; 833 /* done */ 834 return STATUS_SUCCESS; 835 } 836 else 837 { 838 /* buffer too small */ 839 return STATUS_BUFFER_TOO_SMALL; 840 } 841 } 842 843