56c25973745ff5c010a3382e5169f474c9ceb142
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / undoc.cpp
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
12 KSPIN_INTERFACE PinInterfaces[] =
13 {
14 {
15 {STATIC_KSINTERFACESETID_Standard},
16 KSINTERFACE_STANDARD_STREAMING,
17 0
18 },
19 {
20 {STATIC_KSINTERFACESETID_Standard},
21 KSINTERFACE_STANDARD_LOOPED_STREAMING,
22 0
23 }
24 };
25
26
27 NTSTATUS
28 NTAPI
29 KsoDispatchCreateWithGenericFactory(
30 LONG Unknown,
31 PIRP Irp)
32 {
33 UNIMPLEMENTED;
34 return STATUS_NOT_IMPLEMENTED;
35 }
36
37 IIrpTarget *
38 NTAPI
39 KsoGetIrpTargetFromFileObject(
40 PFILE_OBJECT FileObject)
41 {
42 PC_ASSERT(FileObject);
43
44 // IrpTarget is stored in FsContext
45 return (IIrpTarget*)FileObject->FsContext;
46 }
47
48 IIrpTarget *
49 NTAPI
50 KsoGetIrpTargetFromIrp(
51 PIRP Irp)
52 {
53 PKSOBJECT_CREATE_ITEM CreateItem;
54
55 // access the create item
56 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
57
58 // IIrpTarget is stored in Context member
59 return (IIrpTarget*)CreateItem->Context;
60 }
61
62 NTSTATUS
63 NTAPI
64 PcHandlePropertyWithTable(
65 IN PIRP Irp,
66 IN ULONG PropertySetCount,
67 IN PKSPROPERTY_SET PropertySet,
68 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
69 {
70 NTSTATUS Status;
71 PIO_STACK_LOCATION IoStack;
72 PKSP_NODE Property;
73 PPCNODE_DESCRIPTOR Node;
74 PPCPROPERTY_ITEM PropertyItem;
75 ULONG Index;
76 LPGUID Buffer;
77 //PULONG Flags;
78 PPCPROPERTY_REQUEST PropertyRequest;
79
80 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
81
82 /* try first KsPropertyHandler */
83 Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
84
85 // get current irp stack location
86 IoStack = IoGetCurrentIrpStackLocation(Irp);
87
88 // access property
89 Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
90
91 // check if this a GUID_NULL request
92 if (Status == STATUS_NOT_FOUND)
93 {
94 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
95 return Status;
96
97 // check if its a request for a topology node
98 if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
99 {
100 if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
101 {
102 // request is out of bounds
103 Irp->IoStatus.Information = 0;
104 return STATUS_INVALID_PARAMETER;
105 }
106
107 Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
108
109 if (!Node->AutomationTable)
110 {
111 // request is out of bounds
112 Irp->IoStatus.Information = 0;
113 return STATUS_INVALID_PARAMETER;
114 }
115
116 PC_ASSERT(Node->AutomationTable);
117 PC_ASSERT(Node->AutomationTable->PropertyCount);
118 PC_ASSERT(Node->AutomationTable->PropertyItemSize);
119
120 Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
121 if (!Buffer)
122 return STATUS_INSUFFICIENT_RESOURCES;
123
124
125 ULONG Count = 0, SubIndex;
126 PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
127 for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
128 {
129 BOOL Found = FALSE;
130 for (SubIndex = 0; SubIndex < Count; Index++)
131 {
132 if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
133 {
134 Found = TRUE;
135 break;
136 }
137 }
138 if (!Found)
139 {
140 RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
141 Count++;
142 }
143 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
144 }
145
146 Irp->IoStatus.Information = sizeof (GUID) * Count;
147 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
148 {
149 // buffer too small
150 FreeItem(Buffer, TAG_PORTCLASS);
151 return STATUS_MORE_ENTRIES;
152 }
153
154 RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
155 FreeItem(Buffer, TAG_PORTCLASS);
156 return STATUS_SUCCESS;
157 }
158 else /*if (Property->Property.Flags == (KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY) ||
159 Property->Property.Flags == (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY) ||
160 Property->Property.Flags == (KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY)) */
161 {
162 //UNICODE_STRING GuidString;
163
164 if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
165 {
166 // request is out of bounds
167 Irp->IoStatus.Information = 0;
168 return STATUS_INVALID_PARAMETER;
169 }
170
171 Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
172
173 if (!Node->AutomationTable)
174 {
175 // request is out of bounds
176 Irp->IoStatus.Information = 0;
177 return STATUS_NOT_FOUND;
178 }
179
180 PC_ASSERT(Node->AutomationTable);
181 PC_ASSERT(Node->AutomationTable->PropertyCount);
182 PC_ASSERT(Node->AutomationTable->PropertyItemSize);
183
184 PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
185
186 for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
187 {
188 if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
189 {
190 if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
191 {
192 if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
193 {
194 PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
195 PULONG Flags = (PULONG)Irp->UserBuffer;
196
197 /* reset flags */
198 *Flags = 0;
199
200 if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
201 *Flags |= KSPROPERTY_TYPE_SET;
202
203 if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
204 *Flags |= KSPROPERTY_TYPE_GET;
205
206 Irp->IoStatus.Information = sizeof(ULONG);
207
208 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
209 {
210 /* get output buffer */
211 PKSPROPERTY_DESCRIPTION Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
212
213 /* store result */
214 Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
215 Description->PropTypeSet.Set = KSPROPTYPESETID_General;
216 Description->PropTypeSet.Id = 0;
217 Description->PropTypeSet.Flags = 0;
218 Description->MembersListCount = 0;
219 Description->Reserved = 0;
220
221 Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
222 }
223 return STATUS_SUCCESS;
224 }
225 }
226
227
228 PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
229 if (!PropertyRequest)
230 return STATUS_INSUFFICIENT_RESOURCES;
231
232 PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
233 PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
234 PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
235 PropertyRequest->Irp = Irp;
236 PropertyRequest->Node = Property->NodeId;
237 PropertyRequest->PropertyItem = PropertyItem;
238 PropertyRequest->Verb = Property->Property.Flags;
239 PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
240 PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
241 PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
242 PropertyRequest->Value = Irp->UserBuffer;
243
244 Status = PropertyItem->Handler(PropertyRequest);
245
246 if (Status != STATUS_PENDING)
247 {
248 //DPRINT("Status %x ValueSize %u
249
250 Irp->IoStatus.Information = PropertyRequest->ValueSize;
251 ExFreePool(PropertyRequest);
252 }
253 #if 0
254 RtlStringFromGUID(Property->Property.Set, &GuidString);
255 DPRINT("Id %u Flags %x Set %S FlagsItem %x Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, PropertyItem->Flags, Status);
256 RtlFreeUnicodeString(&GuidString);
257 #endif
258 return Status;
259 }
260 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
261 }
262 #if 0
263 RtlStringFromGUID(Property->Property.Set, &GuidString);
264 DPRINT("Id %u Flags %x Set %S Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, Status);
265 RtlFreeUnicodeString(&GuidString);
266 #endif
267 }
268 }
269 return Status;
270 }
271
272 VOID
273 NTAPI
274 PcAcquireFormatResources(
275 LONG Unknown,
276 LONG Unknown2,
277 LONG Unknown3,
278 LONG Unknown4)
279 {
280 UNIMPLEMENTED;
281 }
282
283 NTSTATUS
284 PcAddToEventTable(
285 PVOID Ptr,
286 LONG Unknown2,
287 ULONG Length,
288 LONG Unknown3,
289 LONG Unknown4,
290 LONG Unknown5,
291 LONG Unknown6,
292 LONG Unknown7)
293 {
294 UNIMPLEMENTED;
295 return STATUS_NOT_IMPLEMENTED;
296 }
297
298 NTSTATUS
299 PcAddToPropertyTable(
300 PVOID Ptr,
301 LONG Unknown,
302 LONG Unknown2,
303 LONG Unknown3,
304 CHAR Unknown4)
305 {
306 UNIMPLEMENTED;
307 return STATUS_NOT_IMPLEMENTED;
308 }
309
310 NTSTATUS
311 PcCaptureFormat(
312 LONG Unknown,
313 LONG Unknown2,
314 LONG Unknown3,
315 LONG Unknown4)
316 {
317 UNIMPLEMENTED;
318 return STATUS_NOT_IMPLEMENTED;
319 }
320
321 VOID
322 DumpFilterDescriptor(
323 IN PPCFILTER_DESCRIPTOR FilterDescription)
324 {
325 ULONG Index;
326 PPCPROPERTY_ITEM PropertyItem;
327 UNICODE_STRING GuidString;
328
329 DPRINT("======================\n");
330 DPRINT("Descriptor Automation Table%p\n",FilterDescription->AutomationTable);
331
332 if (FilterDescription->AutomationTable)
333 {
334 DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM));
335 if (FilterDescription->AutomationTable->PropertyCount)
336 {
337 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
338
339 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
340 {
341 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
342 DPRINT("Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
343
344 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
345 }
346 }
347 }
348
349
350 DPRINT("======================\n");
351 }
352
353 NTSTATUS
354 NTAPI
355 PcCreateSubdeviceDescriptor(
356 OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor,
357 IN ULONG InterfaceCount,
358 IN GUID * InterfaceGuids,
359 IN ULONG IdentifierCount,
360 IN KSIDENTIFIER *Identifier,
361 IN ULONG FilterPropertiesCount,
362 IN KSPROPERTY_SET * FilterProperties,
363 IN ULONG Unknown1,
364 IN ULONG Unknown2,
365 IN ULONG PinPropertiesCount,
366 IN KSPROPERTY_SET * PinProperties,
367 IN ULONG EventSetCount,
368 IN KSEVENT_SET * EventSet,
369 IN PPCFILTER_DESCRIPTOR FilterDescription)
370 {
371 SUBDEVICE_DESCRIPTOR * Descriptor;
372 ULONG Index;
373 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
374 PPCPIN_DESCRIPTOR SrcDescriptor;
375
376 Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
377 if (!Descriptor)
378 return STATUS_INSUFFICIENT_RESOURCES;
379
380 // initialize physical / symbolic link connection list
381 InitializeListHead(&Descriptor->SymbolicLinkList);
382 InitializeListHead(&Descriptor->PhysicalConnectionList);
383
384 Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
385 if (!Descriptor->Interfaces)
386 goto cleanup;
387
388 // copy interface guids
389 RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
390 Descriptor->InterfaceCount = InterfaceCount;
391
392 if (FilterPropertiesCount)
393 {
394 /// FIXME
395 /// handle driver properties
396
397 //DumpFilterDescriptor(FilterDescription);
398
399 Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
400 if (! Descriptor->FilterPropertySet)
401 goto cleanup;
402
403 Descriptor->FilterPropertySetCount = FilterPropertiesCount;
404 for(Index = 0; Index < FilterPropertiesCount; Index++)
405 {
406 RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
407 }
408 }
409
410 Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
411 if (!Descriptor->Topology)
412 goto cleanup;
413
414 if (FilterDescription->ConnectionCount)
415 {
416 Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
417 if (!Descriptor->Topology->TopologyConnections)
418 goto cleanup;
419
420 RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
421 Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
422 }
423
424 if (FilterDescription->NodeCount)
425 {
426 Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
427 if (!Descriptor->Topology->TopologyNodes)
428 goto cleanup;
429
430 Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
431 if (!Descriptor->Topology->TopologyNodesNames)
432 goto cleanup;
433
434 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
435 {
436 if (FilterDescription->Nodes[Index].Type)
437 {
438 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], FilterDescription->Nodes[Index].Type, sizeof(GUID));
439 }
440 if (FilterDescription->Nodes[Index].Name)
441 {
442 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], FilterDescription->Nodes[Index].Name, sizeof(GUID));
443 }
444 }
445 Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
446 }
447
448 if (FilterDescription->PinCount)
449 {
450 Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
451 if (!Descriptor->Factory.KsPinDescriptor)
452 goto cleanup;
453
454 Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
455 if (!Descriptor->Factory.Instances)
456 goto cleanup;
457
458 Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
459 Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
460
461 SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
462 DPRINT("Size %u Expected %u Ex Size %u\n", FilterDescription->PinSize, sizeof(KSPIN_DESCRIPTOR), sizeof(KSPIN_DESCRIPTOR_EX));
463
464 // copy pin factories
465 for(Index = 0; Index < FilterDescription->PinCount; Index++)
466 {
467 RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
468
469 Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
470 Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
471
472 DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
473
474 Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
475 Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
476 Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
477 Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
478 SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
479 }
480 }
481
482 Descriptor->DeviceDescriptor = FilterDescription;
483 *OutSubdeviceDescriptor = Descriptor;
484 return STATUS_SUCCESS;
485
486 cleanup:
487 if (Descriptor)
488 {
489 if (Descriptor->Interfaces)
490 FreeItem(Descriptor->Interfaces, TAG_PORTCLASS);
491
492 if (Descriptor->Factory.KsPinDescriptor)
493 FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS);
494
495 FreeItem(Descriptor, TAG_PORTCLASS);
496 }
497 return Status;
498 }
499
500 NTSTATUS
501 NTAPI
502 PcValidateConnectRequest(
503 IN PIRP Irp,
504 IN KSPIN_FACTORY * Factory,
505 OUT PKSPIN_CONNECT * Connect)
506 {
507 return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect);
508 }
509