[PORTCLS]
[reactos.git] / 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 NTSTATUS
12 NTAPI
13 KsoDispatchCreateWithGenericFactory(
14 LONG Unknown,
15 PIRP Irp)
16 {
17 UNIMPLEMENTED;
18 return STATUS_NOT_IMPLEMENTED;
19 }
20
21 IIrpTarget *
22 NTAPI
23 KsoGetIrpTargetFromFileObject(
24 PFILE_OBJECT FileObject)
25 {
26 PC_ASSERT(FileObject);
27
28 // IrpTarget is stored in FsContext
29 return (IIrpTarget*)FileObject->FsContext;
30 }
31
32 IIrpTarget *
33 NTAPI
34 KsoGetIrpTargetFromIrp(
35 PIRP Irp)
36 {
37 PIO_STACK_LOCATION IoStack;
38
39 // get current irp stack location
40 IoStack = IoGetCurrentIrpStackLocation(Irp);
41
42 // IIrpTarget is stored in Context member
43 return (IIrpTarget*)IoStack->FileObject->FsContext;
44 }
45
46 NTSTATUS
47 NTAPI
48 PcHandleEnableEventWithTable(
49 IN PIRP Irp,
50 IN PSUBDEVICE_DESCRIPTOR Descriptor)
51 {
52 // store descriptor
53 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
54
55 // FIXME seh probing
56 return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL);
57 }
58
59 NTSTATUS
60 NTAPI
61 PcHandleDisableEventWithTable(
62 IN PIRP Irp,
63 IN PSUBDEVICE_DESCRIPTOR Descriptor)
64 {
65 // store descriptor
66 KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
67
68 // FIXME seh probing
69
70 return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
71 }
72
73 NTSTATUS
74 NTAPI
75 PcHandlePropertyWithTable(
76 IN PIRP Irp,
77 IN ULONG PropertySetCount,
78 IN PKSPROPERTY_SET PropertySet,
79 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
80 {
81 PIO_STACK_LOCATION IoStack;
82
83 // get current irp stack location
84 IoStack = IoGetCurrentIrpStackLocation(Irp);
85
86 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
87 {
88 // certainly an invalid request
89 return STATUS_INVALID_PARAMETER;
90 }
91
92 // store device descriptor
93 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
94
95 // then try KsPropertyHandler
96 return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
97 }
98
99 VOID
100 NTAPI
101 PcAcquireFormatResources(
102 LONG Unknown,
103 LONG Unknown2,
104 LONG Unknown3,
105 LONG Unknown4)
106 {
107 UNIMPLEMENTED;
108 }
109
110 NTSTATUS
111 PcAddToEventTable(
112 PVOID Ptr,
113 LONG Unknown2,
114 ULONG Length,
115 LONG Unknown3,
116 LONG Unknown4,
117 LONG Unknown5,
118 LONG Unknown6,
119 LONG Unknown7)
120 {
121 UNIMPLEMENTED;
122 return STATUS_NOT_IMPLEMENTED;
123 }
124
125 NTSTATUS
126 NTAPI
127 PropertyItemDispatch(
128 IN PIRP Irp,
129 IN PKSIDENTIFIER Request,
130 IN OUT PVOID Data)
131 {
132 PPCPROPERTY_REQUEST PropertyRequest;
133 PSUBDEVICE_DESCRIPTOR Descriptor;
134 PKSPROPERTY Property;
135 PPCNODE_DESCRIPTOR NodeDescriptor;
136 PKSNODEPROPERTY NodeProperty;
137 PKSPROPERTY_SET PropertySet;
138 PPCPROPERTY_ITEM PropertyItem;
139 PPCAUTOMATION_TABLE NodeAutomation;
140 PIO_STACK_LOCATION IoStack;
141 ULONG InstanceSize, ValueSize, Index;
142 PVOID Instance;
143 NTSTATUS Status;
144
145 // allocate a property request
146 PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
147 if (!PropertyRequest)
148 return STATUS_INSUFFICIENT_RESOURCES;
149
150 // grab device descriptor
151 Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
152
153 // get current irp stack
154 IoStack = IoGetCurrentIrpStackLocation(Irp);
155
156 // get input property request
157 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
158
159 // get property set
160 PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);
161
162 // sanity check
163 PC_ASSERT(Descriptor);
164 PC_ASSERT(Descriptor->UnknownMiniport);
165
166 // get instance / value size
167 InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
168 Instance = Data;
169 ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
170
171 // initialize property request
172 PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
173 PropertyRequest->MinorTarget = Descriptor->UnknownStream;
174 PropertyRequest->Irp = Irp;
175 PropertyRequest->Verb = Property->Flags;
176
177
178 // check if this is filter / pin property request
179 if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
180 {
181 // adjust input buffer size
182 InstanceSize -= sizeof(KSPROPERTY);
183 Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
184
185 // filter / pin property request dont use node field
186 PropertyRequest->Node = MAXULONG;
187 }
188 else if (InstanceSize >= sizeof(KSNODEPROPERTY))
189 {
190 // request is for a node
191 InstanceSize -= sizeof(KSNODEPROPERTY);
192 Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));
193
194 // cast node property request
195 NodeProperty = (PKSNODEPROPERTY)Request;
196
197 // store node id
198 PropertyRequest->Node = NodeProperty->NodeId;
199 }
200 else
201 {
202 // invalid buffer size
203 return STATUS_INVALID_BUFFER_SIZE;
204 }
205
206 // store instance size
207 PropertyRequest->InstanceSize = InstanceSize;
208 PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);
209
210 // store value size
211 PropertyRequest->ValueSize = ValueSize;
212 PropertyRequest->Value = (ValueSize != 0 ? Irp->UserBuffer : NULL);
213
214 // now scan the property set for the attached property set item stored in Relations member
215 if (PropertySet)
216 {
217 // sanity check
218 PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));
219
220 for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
221 {
222 // check if they got the same property id
223 if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
224 {
225 // found item
226 PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
227
228 // done
229 break;
230 }
231 }
232 }
233
234 // check if there has been a property set item attached
235 if (!PropertyRequest->PropertyItem)
236 {
237 // is topology node id valid
238 if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
239 {
240 // get node descriptor
241 NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);
242
243 // get node automation table
244 NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;
245
246 // has it got a automation table
247 if (NodeAutomation)
248 {
249 // now scan the properties and check if it supports this request
250 PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
251 for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
252 {
253 // are they same property
254 if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
255 {
256 if (PropertyItem->Id == Property->Id)
257 {
258 // found match
259 PropertyRequest->PropertyItem = PropertyItem;
260
261 // done
262 break;
263 }
264 }
265
266 // move to next property item
267 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
268 }
269 }
270 }
271 }
272
273 if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
274 {
275 // now call the handler
276 UNICODE_STRING GuidBuffer;
277 RtlStringFromGUID(Property->Set, &GuidBuffer);
278 DPRINT1("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p PropertyItemFlags %lx PropertyItemId %lu\n",
279 PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
280 PropertyRequest->PropertyItem->Handler, PropertyRequest, PropertyRequest->PropertyItem->Flags, PropertyRequest->PropertyItem->Id);
281 #if 1
282 Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
283 DPRINT1("Status %lx ValueSize %lu Information %lu\n", Status, PropertyRequest->ValueSize, Irp->IoStatus.Information);
284 #else
285 Status = STATUS_NOT_FOUND;
286 #endif
287 Irp->IoStatus.Information = PropertyRequest->ValueSize;
288
289 if (Status != STATUS_PENDING)
290 {
291 // free property request
292 FreeItem(PropertyRequest, TAG_PORTCLASS);
293 }
294 }
295 else
296 {
297 FreeItem(PropertyRequest, TAG_PORTCLASS);
298 Status = STATUS_NOT_FOUND;
299 }
300
301 /* done */
302 return Status;
303 }
304
305 NTSTATUS
306 PcAddToPropertyTable(
307 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
308 IN PPCPROPERTY_ITEM PropertyItem,
309 IN ULONG bNode)
310 {
311 ULONG bFound = FALSE;
312 ULONG Index, PropertySetIndex, PropertySetItemIndex;
313 PKSPROPERTY_SET NewPropertySet;
314 PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
315 LPGUID Guid;
316 //UNICODE_STRING GuidBuffer;
317
318 ASSERT(PropertyItem->Set);
319 // RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
320 // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
321
322
323
324 //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
325 // first step check if the property set is present already
326 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
327 {
328
329 //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
330 //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
331 if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
332 {
333 // property set is already present
334 bFound = TRUE;
335 PropertySetIndex = Index;
336
337 // break out
338 break;
339 }
340 }
341
342 // is the property set present
343 if (!bFound)
344 {
345 // need to allocate a property set
346 NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
347 if (!NewPropertySet)
348 {
349 // out of memory
350 return STATUS_INSUFFICIENT_RESOURCES;
351 }
352
353 // need to allocate property set guid
354 Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
355 if (!Guid)
356 {
357 // out of memory
358 FreeItem(NewPropertySet, TAG_PORTCLASS);
359 return STATUS_INSUFFICIENT_RESOURCES;
360 }
361
362 // are any existing property sets
363 if (SubDeviceDescriptor->FilterPropertySetCount)
364 {
365 // copy property sets
366 RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
367
368 // release memory
369 FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
370 }
371
372 // store new property set descriptors
373 SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
374
375 // store index
376 PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
377
378 // increment property set count
379 SubDeviceDescriptor->FilterPropertySetCount++;
380
381 // copy property guid
382 RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
383
384 // initialize property set
385 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
386 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
387 }
388
389 // as the property set has been indentified, now search for duplicate property set item entries
390 FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
391 bFound = FALSE;
392
393 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
394 {
395 // now search for an equal property set item
396 if (FilterPropertyItem->PropertyId == PropertyItem->Id)
397 {
398 // found existing property set item
399 bFound = TRUE;
400 PropertySetItemIndex = Index;
401 break;
402 }
403
404 // move to next entry
405 FilterPropertyItem++;
406 }
407
408 if (!bFound)
409 {
410 // need to allocate memory for new property set item
411 NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
412 if (!NewFilterPropertyItem)
413 {
414 // out of memory
415 return STATUS_INSUFFICIENT_RESOURCES;
416 }
417
418 // are any existing property set items
419 if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
420 {
421 // copy property item sets
422 RtlMoveMemory(NewFilterPropertyItem,
423 (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
424 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
425
426 // release old descriptors
427 FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
428 }
429
430 // store new descriptor
431 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
432
433 // store index
434 PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
435
436 // increment property item set count
437 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
438
439 // now initialize property item
440 FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
441 FilterPropertyItem->PropertyId = PropertyItem->Id;
442 FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
443 FilterPropertyItem->MinData = 0;
444
445 // are any set operations supported
446 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
447 {
448 // setup handler
449 FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
450 }
451
452 // are set operation supported
453 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
454 {
455 // setup handler
456 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
457 }
458
459 // are get operations supported
460 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
461 {
462 // setup handler
463 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
464 }
465
466 // are basic support operations supported
467 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
468 {
469 // setup handler
470 FilterPropertyItem->SupportHandler = PropertyItemDispatch;
471 }
472
473 if (!bNode)
474 {
475 // store property item in relations
476 // only store property item of filter properties / pin properties
477 // because filter & pin properties do not require a specific context
478 // on the other hand node properties are specifically bound to a node
479
480 FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
481 }
482 }
483 else
484 {
485 // property set item handler already present
486
487 if (bNode)
488 {
489 // filter & pin properties should not be exposed on a node
490 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
491 }
492 else
493 {
494 // node properties should not be exposed on a filter & pin
495 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
496 }
497 }
498
499 // done
500 return STATUS_SUCCESS;
501 }
502
503 NTSTATUS
504 PcCaptureFormat(
505 LONG Unknown,
506 LONG Unknown2,
507 LONG Unknown3,
508 LONG Unknown4)
509 {
510 UNIMPLEMENTED;
511 return STATUS_NOT_IMPLEMENTED;
512 }
513
514 VOID
515 DumpFilterDescriptor(
516 IN PPCFILTER_DESCRIPTOR FilterDescription)
517 {
518 ULONG Index, SubIndex;
519 PPCPROPERTY_ITEM PropertyItem;
520 PPCEVENT_ITEM EventItem;
521 PPCNODE_DESCRIPTOR NodeDescriptor;
522 UNICODE_STRING GuidString;
523
524
525
526 DPRINT("======================\n");
527 DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable);
528
529 if (FilterDescription->AutomationTable)
530 {
531 DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u Events %u EventItemSize %u expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM),
532 FilterDescription->AutomationTable->EventCount, FilterDescription->AutomationTable->EventItemSize, sizeof(PCEVENT_ITEM));
533 if (FilterDescription->AutomationTable->PropertyCount)
534 {
535 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
536
537 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
538 {
539 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
540 DPRINT("Property Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
541
542 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
543 }
544
545 EventItem = (PPCEVENT_ITEM)FilterDescription->AutomationTable->Events;
546 for(Index = 0; Index < FilterDescription->AutomationTable->EventCount; Index++)
547 {
548 RtlStringFromGUID(*EventItem->Set, &GuidString);
549 DPRINT("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags);
550
551 EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize);
552 }
553
554 }
555 }
556
557 if (FilterDescription->Nodes)
558 {
559 DPRINT("NodeCount %u NodeSize %u expected %u\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR));
560 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
561 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
562 {
563 DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable);
564
565 if (NodeDescriptor->AutomationTable)
566 {
567 DPRINT(" Index %u EventCount %u\n", Index, NodeDescriptor->AutomationTable->EventCount);
568 EventItem = (PPCEVENT_ITEM)NodeDescriptor->AutomationTable->Events;
569 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->EventCount; SubIndex++)
570 {
571 RtlStringFromGUID(*EventItem->Set, &GuidString);
572 DPRINT(" EventIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, EventItem->Id, EventItem->Flags);
573
574 EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + NodeDescriptor->AutomationTable->EventItemSize);
575 }
576
577 DPRINT1(" Index %u PropertyCount %u\n", Index, NodeDescriptor->AutomationTable->PropertyCount);
578 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
579 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
580 {
581 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
582 DPRINT1(" PropertyIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
583
584 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
585 }
586 }
587
588
589 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
590 }
591
592
593
594 }
595
596 DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount);
597
598 if (FilterDescription->ConnectionCount)
599 {
600 DPRINT("------ Start of Nodes Connections ----------------\n");
601 for(Index = 0; Index < FilterDescription->ConnectionCount; Index++)
602 {
603 DPRINT1("Index %ld FromPin %ld FromNode %ld -> ToPin %ld ToNode %ld\n", Index,
604 FilterDescription->Connections[Index].FromNodePin,
605 FilterDescription->Connections[Index].FromNode,
606 FilterDescription->Connections[Index].ToNodePin,
607 FilterDescription->Connections[Index].ToNode);
608 }
609 DPRINT("------ End of Nodes Connections----------------\n");
610 }
611
612 DPRINT1("======================\n");
613 }
614
615 NTSTATUS
616 NTAPI
617 PcCreateSubdeviceDescriptor(
618 OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor,
619 IN ULONG InterfaceCount,
620 IN GUID * InterfaceGuids,
621 IN ULONG IdentifierCount,
622 IN KSIDENTIFIER *Identifier,
623 IN ULONG FilterPropertiesCount,
624 IN KSPROPERTY_SET * FilterProperties,
625 IN ULONG Unknown1,
626 IN ULONG Unknown2,
627 IN ULONG PinPropertiesCount,
628 IN KSPROPERTY_SET * PinProperties,
629 IN ULONG EventSetCount,
630 IN KSEVENT_SET * EventSet,
631 IN PPCFILTER_DESCRIPTOR FilterDescription)
632 {
633 SUBDEVICE_DESCRIPTOR * Descriptor;
634 ULONG Index, SubIndex;
635 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
636 PPCPIN_DESCRIPTOR SrcDescriptor;
637 PPCNODE_DESCRIPTOR NodeDescriptor;
638 PPCPROPERTY_ITEM PropertyItem;
639
640 // allocate subdevice descriptor
641 Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
642 if (!Descriptor)
643 return STATUS_INSUFFICIENT_RESOURCES;
644
645 // initialize physical / symbolic link connection list
646 InitializeListHead(&Descriptor->SymbolicLinkList);
647 InitializeListHead(&Descriptor->PhysicalConnectionList);
648
649 //FIXME add driver category guids
650 Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
651 if (!Descriptor->Interfaces)
652 goto cleanup;
653
654 // copy interface guids
655 RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
656 Descriptor->InterfaceCount = InterfaceCount;
657
658 //DumpFilterDescriptor(FilterDescription);
659
660 // are any property sets supported by the portcls
661 if (FilterPropertiesCount)
662 {
663 // first allocate filter properties set
664 Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
665 if (! Descriptor->FilterPropertySet)
666 goto cleanup;
667
668 // now copy all filter property sets
669 Descriptor->FilterPropertySetCount = FilterPropertiesCount;
670 for(Index = 0; Index < FilterPropertiesCount; Index++)
671 {
672 // copy property set
673 RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
674
675 if (Descriptor->FilterPropertySet[Index].PropertiesCount)
676 {
677 // copy property items to make sure they are dynamically allocated
678 Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
679 if (!Descriptor->FilterPropertySet[Index].PropertyItem)
680 {
681 // no memory
682 goto cleanup;
683 }
684
685 // copy filter property items
686 RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
687 }
688 }
689 }
690
691 // now check if the filter descriptor supports filter properties
692 if (FilterDescription->AutomationTable)
693 {
694 // get first entry
695 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
696
697 // copy driver filter property sets
698 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
699 {
700 // add the property item
701 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
702
703 // check for success
704 if (Status != STATUS_SUCCESS)
705 {
706 // goto cleanup
707 goto cleanup;
708 }
709
710 // move to next entry
711 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
712 }
713 }
714
715 // check if the filter has pins
716 if (FilterDescription->PinCount)
717 {
718 // allocate pin factory descriptors
719 Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
720 if (!Descriptor->Factory.KsPinDescriptor)
721 goto cleanup;
722
723 // allocate pin instance info
724 Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
725 if (!Descriptor->Factory.Instances)
726 goto cleanup;
727
728 // initialize pin factory descriptor
729 Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
730 Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
731
732 // grab first entry
733 SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
734
735 // copy pin factories
736 for(Index = 0; Index < FilterDescription->PinCount; Index++)
737 {
738 // copy pin descriptor
739 RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
740
741 // initialize pin factory instance data
742 Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
743 Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
744 Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
745 Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
746
747 // check if the descriptor has an automation table
748 if (SrcDescriptor->AutomationTable)
749 {
750 // it has, grab first entry
751 PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
752
753 // now add all supported property items
754 for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
755 {
756 // add the property item to the table
757 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
758
759 // check for success
760 if (Status != STATUS_SUCCESS)
761 {
762 // goto cleanup
763 goto cleanup;
764 }
765
766 // move to next entry
767 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
768 }
769 }
770
771 // move to next entry
772 SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
773 }
774 }
775
776 // allocate topology descriptor
777 Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
778 if (!Descriptor->Topology)
779 goto cleanup;
780
781 // are there any connections
782 if (FilterDescription->ConnectionCount)
783 {
784 // allocate connection descriptor
785 Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
786 if (!Descriptor->Topology->TopologyConnections)
787 goto cleanup;
788
789 // copy connection descriptor
790 RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
791
792 // store connection count
793 Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
794 }
795
796 // does the filter have nodes
797 if (FilterDescription->NodeCount)
798 {
799 // allocate topology node types array
800 Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
801 if (!Descriptor->Topology->TopologyNodes)
802 goto cleanup;
803
804 // allocate topology node names array
805 Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
806 if (!Descriptor->Topology->TopologyNodesNames)
807 goto cleanup;
808
809 // grab first entry
810 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
811
812 // iterate all nodes and copy node types / names and node properties
813 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
814 {
815 // does it have a type
816 if (NodeDescriptor->Type)
817 {
818 // copy node type
819 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
820 }
821
822 // does it have a node name
823 if (NodeDescriptor->Name)
824 {
825 // copy node name
826 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
827 }
828
829 // check if has an automation table
830 if (NodeDescriptor->AutomationTable)
831 {
832 // grab first entry
833 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
834
835 // copy all node properties into the global property set
836 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
837 {
838 // add to property set
839 Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
840
841 // check for success
842 if (Status != STATUS_SUCCESS)
843 {
844 // failed
845 goto cleanup;
846 }
847
848 // move to next property item
849 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
850 }
851 }
852
853 // move to next descriptor
854 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
855 }
856
857 // now store the topology node count
858 Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
859 }
860
861 // store descriptor
862 Descriptor->DeviceDescriptor = FilterDescription;
863
864 // store result
865 *OutSubdeviceDescriptor = Descriptor;
866 // done
867 return STATUS_SUCCESS;
868
869 cleanup:
870 if (Descriptor)
871 {
872 if (Descriptor->Interfaces)
873 FreeItem(Descriptor->Interfaces, TAG_PORTCLASS);
874
875 if (Descriptor->Factory.KsPinDescriptor)
876 FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS);
877
878 FreeItem(Descriptor, TAG_PORTCLASS);
879 }
880 return Status;
881 }
882
883 NTSTATUS
884 NTAPI
885 PcValidateConnectRequest(
886 IN PIRP Irp,
887 IN KSPIN_FACTORY * Factory,
888 OUT PKSPIN_CONNECT * Connect)
889 {
890 return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect);
891 }
892