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