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