1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/propertyhandler.cpp 5 * PURPOSE: Pin property handler 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 NTSTATUS 15 HandlePropertyInstances( 16 IN PIO_STATUS_BLOCK IoStatus, 17 IN PKSIDENTIFIER Request, 18 IN OUT PVOID Data, 19 IN PSUBDEVICE_DESCRIPTOR Descriptor, 20 IN BOOL Global, 21 IN ISubdevice *SubDevice) 22 { 23 KSPIN_CINSTANCES * Instances; 24 KSP_PIN * Pin = (KSP_PIN*)Request; 25 ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible; 26 NTSTATUS Status; 27 28 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount) 29 { 30 IoStatus->Information = 0; 31 IoStatus->Status = STATUS_INVALID_PARAMETER; 32 return STATUS_INVALID_PARAMETER; 33 } 34 35 Instances = (KSPIN_CINSTANCES*)Data; 36 37 // check if the miniport supports the IPinCount interface 38 Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); 39 40 if (NT_SUCCESS(Status)) 41 { 42 if (Global) 43 { 44 Instances->PossibleCount = GlobalPossible; 45 Instances->CurrentCount = GlobalCurrent; 46 } 47 else 48 { 49 Instances->PossibleCount = FilterPossible; 50 Instances->CurrentCount = FilterCurrent; 51 } 52 } 53 else 54 { 55 if (Global) 56 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxGlobalInstanceCount; 57 else 58 Instances->PossibleCount = Descriptor->Factory.Instances[Pin->PinId].MaxFilterInstanceCount; 59 60 Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount; 61 } 62 63 IoStatus->Information = sizeof(KSPIN_CINSTANCES); 64 IoStatus->Status = STATUS_SUCCESS; 65 return STATUS_SUCCESS; 66 } 67 68 NTSTATUS 69 HandleNecessaryPropertyInstances( 70 IN PIO_STATUS_BLOCK IoStatus, 71 IN PKSIDENTIFIER Request, 72 IN OUT PVOID Data, 73 IN PSUBDEVICE_DESCRIPTOR Descriptor, 74 IN ISubdevice *SubDevice) 75 { 76 PULONG Result; 77 KSP_PIN * Pin = (KSP_PIN*)Request; 78 ULONG FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible; 79 NTSTATUS Status; 80 81 if (Pin->PinId >= Descriptor->Factory.PinDescriptorCount) 82 { 83 IoStatus->Information = 0; 84 IoStatus->Status = STATUS_INVALID_PARAMETER; 85 return STATUS_INVALID_PARAMETER; 86 } 87 88 Result = (PULONG)Data; 89 90 // check if the miniport supports the IPinCount interface 91 Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); 92 93 if (NT_SUCCESS(Status)) 94 { 95 *Result = FilterNecessary; 96 } 97 else 98 { 99 *Result = Descriptor->Factory.Instances[Pin->PinId].MinFilterInstanceCount; 100 } 101 102 IoStatus->Information = sizeof(ULONG); 103 IoStatus->Status = STATUS_SUCCESS; 104 return STATUS_SUCCESS; 105 } 106 107 NTSTATUS 108 HandleDataIntersection( 109 IN PIO_STATUS_BLOCK IoStatus, 110 IN PKSIDENTIFIER Request, 111 IN OUT PVOID Data, 112 IN ULONG DataLength, 113 IN PSUBDEVICE_DESCRIPTOR Descriptor, 114 IN ISubdevice *SubDevice) 115 { 116 KSP_PIN * Pin = (KSP_PIN*)Request; 117 PKSMULTIPLE_ITEM MultipleItem; 118 PKSDATARANGE DataRange; 119 NTSTATUS Status = STATUS_NO_MATCH; 120 ULONG Index, Length; 121 122 // Access parameters 123 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1); 124 DataRange = (PKSDATARANGE)(MultipleItem + 1); 125 126 for(Index = 0; Index < MultipleItem->Count; Index++) 127 { 128 // Call miniport's proprietary handler 129 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRangesCount); 130 PC_ASSERT(Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0]); 131 Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0], 132 DataLength, Data, &Length); 133 134 if (Status == STATUS_SUCCESS) 135 { 136 IoStatus->Information = Length; 137 break; 138 } 139 DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize); 140 } 141 142 IoStatus->Status = Status; 143 return Status; 144 } 145 146 NTSTATUS 147 HandlePhysicalConnection( 148 IN PIO_STATUS_BLOCK IoStatus, 149 IN PKSIDENTIFIER Request, 150 IN ULONG RequestLength, 151 IN OUT PVOID Data, 152 IN ULONG DataLength, 153 IN PSUBDEVICE_DESCRIPTOR Descriptor) 154 { 155 PKSP_PIN Pin; 156 PLIST_ENTRY Entry; 157 //PKSPIN_PHYSICALCONNECTION Connection; 158 PPHYSICAL_CONNECTION_ENTRY ConEntry; 159 160 // get pin 161 Pin = (PKSP_PIN)Request; 162 163 if (RequestLength < sizeof(KSP_PIN)) 164 { 165 // input buffer must be at least sizeof KSP_PIN 166 DPRINT("input length too small\n"); 167 return STATUS_INVALID_PARAMETER; 168 } 169 170 if (IsListEmpty(&Descriptor->PhysicalConnectionList)) 171 { 172 DPRINT("no connection\n"); 173 return STATUS_NOT_FOUND; 174 } 175 176 // get first item 177 Entry = Descriptor->PhysicalConnectionList.Flink; 178 179 do 180 { 181 ConEntry = (PPHYSICAL_CONNECTION_ENTRY)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION_ENTRY, Entry); 182 183 if (ConEntry->FromPin == Pin->PinId) 184 { 185 //Connection = (PKSPIN_PHYSICALCONNECTION)Data; 186 DPRINT("FoundEntry %S Size %u\n", ConEntry->Connection.SymbolicLinkName, ConEntry->Connection.Size); 187 IoStatus->Information = ConEntry->Connection.Size; 188 189 if (!DataLength) 190 { 191 IoStatus->Information = ConEntry->Connection.Size; 192 return STATUS_MORE_ENTRIES; 193 } 194 195 if (DataLength < ConEntry->Connection.Size) 196 { 197 return STATUS_BUFFER_TOO_SMALL; 198 } 199 200 RtlMoveMemory(Data, &ConEntry->Connection, ConEntry->Connection.Size); 201 return STATUS_SUCCESS; 202 } 203 204 // move to next item 205 Entry = Entry->Flink; 206 }while(Entry != &Descriptor->PhysicalConnectionList); 207 208 IoStatus->Information = 0; 209 return STATUS_NOT_FOUND; 210 } 211 212 NTSTATUS 213 NTAPI 214 PinPropertyHandler( 215 IN PIRP Irp, 216 IN PKSIDENTIFIER Request, 217 IN OUT PVOID Data) 218 { 219 PIO_STACK_LOCATION IoStack; 220 //PKSOBJECT_CREATE_ITEM CreateItem; 221 PSUBDEVICE_DESCRIPTOR Descriptor; 222 IIrpTarget * IrpTarget; 223 IPort *Port; 224 ISubdevice *SubDevice; 225 PDISPATCH_CONTEXT DispatchContext; 226 227 NTSTATUS Status = STATUS_UNSUCCESSFUL; 228 229 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 230 PC_ASSERT(Descriptor); 231 232 // get current irp stack 233 IoStack = IoGetCurrentIrpStackLocation(Irp); 234 235 // get dispatch context 236 DispatchContext = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; 237 238 // Get the IrpTarget 239 IrpTarget = DispatchContext->Target; 240 PC_ASSERT(IrpTarget); 241 242 // Get the parent 243 Status = IrpTarget->QueryInterface(IID_IPort, (PVOID*)&Port); 244 if (!NT_SUCCESS(Status)) 245 { 246 DPRINT("Failed to obtain IPort interface from filter\n"); 247 Irp->IoStatus.Information = 0; 248 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 249 return STATUS_UNSUCCESSFUL; 250 } 251 252 // Get private ISubdevice interface 253 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice); 254 if (!NT_SUCCESS(Status)) 255 { 256 DPRINT("Failed to obtain ISubdevice interface from port driver\n"); 257 DbgBreakPoint(); 258 while(TRUE); 259 } 260 261 // get current stack location 262 IoStack = IoGetCurrentIrpStackLocation(Irp); 263 264 switch(Request->Id) 265 { 266 case KSPROPERTY_PIN_CTYPES: 267 case KSPROPERTY_PIN_DATAFLOW: 268 case KSPROPERTY_PIN_DATARANGES: 269 case KSPROPERTY_PIN_INTERFACES: 270 case KSPROPERTY_PIN_MEDIUMS: 271 case KSPROPERTY_PIN_COMMUNICATION: 272 case KSPROPERTY_PIN_CATEGORY: 273 case KSPROPERTY_PIN_NAME: 274 case KSPROPERTY_PIN_PROPOSEDATAFORMAT: 275 Status = KsPinPropertyHandler(Irp, Request, Data, Descriptor->Factory.PinDescriptorCount, Descriptor->Factory.KsPinDescriptor); 276 break; 277 case KSPROPERTY_PIN_GLOBALCINSTANCES: 278 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, TRUE, SubDevice); 279 break; 280 case KSPROPERTY_PIN_CINSTANCES: 281 Status = HandlePropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, FALSE, SubDevice); 282 break; 283 case KSPROPERTY_PIN_NECESSARYINSTANCES: 284 Status = HandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, Descriptor, SubDevice); 285 break; 286 287 case KSPROPERTY_PIN_DATAINTERSECTION: 288 Status = HandleDataIntersection(&Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor, SubDevice); 289 break; 290 case KSPROPERTY_PIN_PHYSICALCONNECTION: 291 Status = HandlePhysicalConnection(&Irp->IoStatus, Request, IoStack->Parameters.DeviceIoControl.InputBufferLength, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Descriptor); 292 break; 293 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: 294 UNIMPLEMENTED; 295 Status = STATUS_NOT_IMPLEMENTED; 296 break; 297 default: 298 UNIMPLEMENTED; 299 Status = STATUS_UNSUCCESSFUL; 300 } 301 302 // Release reference 303 Port->Release(); 304 305 // Release subdevice reference 306 SubDevice->Release(); 307 308 return Status; 309 } 310 311 NTSTATUS 312 NTAPI 313 TopologyPropertyHandler( 314 IN PIRP Irp, 315 IN PKSIDENTIFIER Request, 316 IN OUT PVOID Data) 317 { 318 PSUBDEVICE_DESCRIPTOR Descriptor; 319 320 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); 321 322 return KsTopologyPropertyHandler(Irp, Request, Data, Descriptor->Topology); 323 } 324