[PORTCLS]
[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 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\n",
279 PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
280 PropertyRequest->PropertyItem->Handler, PropertyRequest);
281 #if 0
282 Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
283 #else
284 Status = STATUS_NOT_FOUND;
285 #endif
286 Irp->IoStatus.Information = PropertyRequest->ValueSize;
287
288 if (Status != STATUS_PENDING)
289 {
290 // free property request
291 FreeItem(PropertyRequest, TAG_PORTCLASS);
292 }
293 }
294 else
295 {
296 FreeItem(PropertyRequest, TAG_PORTCLASS);
297 Status = STATUS_NOT_FOUND;
298 }
299
300 /* done */
301 return Status;
302 }
303
304 NTSTATUS
305 PcAddToPropertyTable(
306 IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
307 IN PPCPROPERTY_ITEM PropertyItem,
308 IN ULONG bNode)
309 {
310 ULONG bFound = FALSE;
311 ULONG Index, PropertySetIndex, PropertySetItemIndex;
312 PKSPROPERTY_SET NewPropertySet;
313 PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
314 LPGUID Guid;
315 //UNICODE_STRING GuidBuffer;
316
317 ASSERT(PropertyItem->Set);
318 // RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
319 // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
320
321
322
323 //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
324 // first step check if the property set is present already
325 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
326 {
327
328 //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
329 //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
330 if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
331 {
332 // property set is already present
333 bFound = TRUE;
334 PropertySetIndex = Index;
335
336 // break out
337 break;
338 }
339 }
340
341 // is the property set present
342 if (!bFound)
343 {
344 // need to allocate a property set
345 NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
346 if (!NewPropertySet)
347 {
348 // out of memory
349 return STATUS_INSUFFICIENT_RESOURCES;
350 }
351
352 // need to allocate property set guid
353 Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
354 if (!Guid)
355 {
356 // out of memory
357 FreeItem(NewPropertySet, TAG_PORTCLASS);
358 return STATUS_INSUFFICIENT_RESOURCES;
359 }
360
361 // are any existing property sets
362 if (SubDeviceDescriptor->FilterPropertySetCount)
363 {
364 // copy property sets
365 RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
366
367 // release memory
368 FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
369 }
370
371 // store new property set descriptors
372 SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
373
374 // store index
375 PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
376
377 // increment property set count
378 SubDeviceDescriptor->FilterPropertySetCount++;
379
380 // copy property guid
381 RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
382
383 // initialize property set
384 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
385 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
386 }
387
388 // as the property set has been indentified, now search for duplicate property set item entries
389 FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
390 bFound = FALSE;
391
392 for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
393 {
394 // now search for an equal property set item
395 if (FilterPropertyItem->PropertyId == PropertyItem->Id)
396 {
397 // found existing property set item
398 bFound = TRUE;
399 PropertySetItemIndex = Index;
400 break;
401 }
402
403 // move to next entry
404 FilterPropertyItem++;
405 }
406
407 if (!bFound)
408 {
409 // need to allocate memory for new property set item
410 NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
411 if (!NewFilterPropertyItem)
412 {
413 // out of memory
414 return STATUS_INSUFFICIENT_RESOURCES;
415 }
416
417 // are any existing property set items
418 if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
419 {
420 // copy property item sets
421 RtlMoveMemory(NewFilterPropertyItem,
422 (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
423 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
424
425 // release old descriptors
426 FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
427 }
428
429 // store new descriptor
430 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
431
432 // store index
433 PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
434
435 // increment property item set count
436 SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
437
438 // now initialize property item
439 FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
440 FilterPropertyItem->PropertyId = PropertyItem->Id;
441 FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
442 FilterPropertyItem->MinData = 0;
443
444 // are any set operations supported
445 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
446 {
447 // setup handler
448 FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
449 }
450
451 // are set operation supported
452 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
453 {
454 // setup handler
455 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
456 }
457
458 // are get operations supported
459 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
460 {
461 // setup handler
462 FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
463 }
464
465 // are basic support operations supported
466 if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
467 {
468 // setup handler
469 FilterPropertyItem->SupportHandler = PropertyItemDispatch;
470 }
471
472 if (!bNode)
473 {
474 // store property item in relations
475 // only store property item of filter properties / pin properties
476 // because filter & pin properties do not require a specific context
477 // on the other hand node properties are specifically bound to a node
478
479 FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
480 }
481 }
482 else
483 {
484 // property set item handler already present
485
486 if (bNode)
487 {
488 // filter & pin properties should not be exposed on a node
489 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
490 }
491 else
492 {
493 // node properties should not be exposed on a filter & pin
494 ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
495 }
496 }
497
498 // done
499 return STATUS_SUCCESS;
500 }
501
502 NTSTATUS
503 PcCaptureFormat(
504 LONG Unknown,
505 LONG Unknown2,
506 LONG Unknown3,
507 LONG Unknown4)
508 {
509 UNIMPLEMENTED;
510 return STATUS_NOT_IMPLEMENTED;
511 }
512
513 VOID
514 DumpFilterDescriptor(
515 IN PPCFILTER_DESCRIPTOR FilterDescription)
516 {
517 ULONG Index, SubIndex;
518 PPCPROPERTY_ITEM PropertyItem;
519 PPCEVENT_ITEM EventItem;
520 PPCNODE_DESCRIPTOR NodeDescriptor;
521 UNICODE_STRING GuidString;
522
523
524
525 DPRINT("======================\n");
526 DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable);
527
528 if (FilterDescription->AutomationTable)
529 {
530 DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u Events %u EventItemSize %u expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM),
531 FilterDescription->AutomationTable->EventCount, FilterDescription->AutomationTable->EventItemSize, sizeof(PCEVENT_ITEM));
532 if (FilterDescription->AutomationTable->PropertyCount)
533 {
534 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
535
536 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
537 {
538 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
539 DPRINT("Property Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
540
541 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
542 }
543
544 EventItem = (PPCEVENT_ITEM)FilterDescription->AutomationTable->Events;
545 for(Index = 0; Index < FilterDescription->AutomationTable->EventCount; Index++)
546 {
547 RtlStringFromGUID(*EventItem->Set, &GuidString);
548 DPRINT("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags);
549
550 EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize);
551 }
552
553 }
554 }
555
556 if (FilterDescription->Nodes)
557 {
558 DPRINT("NodeCount %u NodeSize %u expected %u\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR));
559 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
560 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
561 {
562 DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable);
563
564 if (NodeDescriptor->AutomationTable)
565 {
566 DPRINT(" Index %u EventCount %u\n", Index, NodeDescriptor->AutomationTable->EventCount);
567 EventItem = (PPCEVENT_ITEM)NodeDescriptor->AutomationTable->Events;
568 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->EventCount; SubIndex++)
569 {
570 RtlStringFromGUID(*EventItem->Set, &GuidString);
571 DPRINT(" EventIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, EventItem->Id, EventItem->Flags);
572
573 EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + NodeDescriptor->AutomationTable->EventItemSize);
574 }
575
576 DPRINT1(" Index %u PropertyCount %u\n", Index, NodeDescriptor->AutomationTable->PropertyCount);
577 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
578 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
579 {
580 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
581 DPRINT1(" PropertyIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
582
583 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
584 }
585 }
586
587
588 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
589 }
590
591
592
593 }
594
595 DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount);
596
597 if (FilterDescription->ConnectionCount)
598 {
599 DPRINT("------ Start of Nodes Connections ----------------\n");
600 for(Index = 0; Index < FilterDescription->ConnectionCount; Index++)
601 {
602 DPRINT1("Index %ld FromPin %ld FromNode %ld -> ToPin %ld ToNode %ld\n", Index,
603 FilterDescription->Connections[Index].FromNodePin,
604 FilterDescription->Connections[Index].FromNode,
605 FilterDescription->Connections[Index].ToNodePin,
606 FilterDescription->Connections[Index].ToNode);
607 }
608 DPRINT("------ End of Nodes Connections----------------\n");
609 }
610
611 DPRINT1("======================\n");
612 }
613
614 NTSTATUS
615 NTAPI
616 PcCreateSubdeviceDescriptor(
617 OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor,
618 IN ULONG InterfaceCount,
619 IN GUID * InterfaceGuids,
620 IN ULONG IdentifierCount,
621 IN KSIDENTIFIER *Identifier,
622 IN ULONG FilterPropertiesCount,
623 IN KSPROPERTY_SET * FilterProperties,
624 IN ULONG Unknown1,
625 IN ULONG Unknown2,
626 IN ULONG PinPropertiesCount,
627 IN KSPROPERTY_SET * PinProperties,
628 IN ULONG EventSetCount,
629 IN KSEVENT_SET * EventSet,
630 IN PPCFILTER_DESCRIPTOR FilterDescription)
631 {
632 SUBDEVICE_DESCRIPTOR * Descriptor;
633 ULONG Index, SubIndex;
634 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
635 PPCPIN_DESCRIPTOR SrcDescriptor;
636 PPCNODE_DESCRIPTOR NodeDescriptor;
637 PPCPROPERTY_ITEM PropertyItem;
638
639 // allocate subdevice descriptor
640 Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
641 if (!Descriptor)
642 return STATUS_INSUFFICIENT_RESOURCES;
643
644 // initialize physical / symbolic link connection list
645 InitializeListHead(&Descriptor->SymbolicLinkList);
646 InitializeListHead(&Descriptor->PhysicalConnectionList);
647
648 //FIXME add driver category guids
649 Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
650 if (!Descriptor->Interfaces)
651 goto cleanup;
652
653 // copy interface guids
654 RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
655 Descriptor->InterfaceCount = InterfaceCount;
656
657 //DumpFilterDescriptor(FilterDescription);
658
659 // are any property sets supported by the portcls
660 if (FilterPropertiesCount)
661 {
662 // first allocate filter properties set
663 Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
664 if (! Descriptor->FilterPropertySet)
665 goto cleanup;
666
667 // now copy all filter property sets
668 Descriptor->FilterPropertySetCount = FilterPropertiesCount;
669 for(Index = 0; Index < FilterPropertiesCount; Index++)
670 {
671 // copy property set
672 RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
673
674 if (Descriptor->FilterPropertySet[Index].PropertiesCount)
675 {
676 // copy property items to make sure they are dynamically allocated
677 Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
678 if (!Descriptor->FilterPropertySet[Index].PropertyItem)
679 {
680 // no memory
681 goto cleanup;
682 }
683
684 // copy filter property items
685 RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
686 }
687 }
688 }
689
690 // now check if the filter descriptor supports filter properties
691 if (FilterDescription->AutomationTable)
692 {
693 // get first entry
694 PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
695
696 // copy driver filter property sets
697 for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
698 {
699 // add the property item
700 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
701
702 // check for success
703 if (Status != STATUS_SUCCESS)
704 {
705 // goto cleanup
706 goto cleanup;
707 }
708
709 // move to next entry
710 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
711 }
712 }
713
714 // check if the filter has pins
715 if (FilterDescription->PinCount)
716 {
717 // allocate pin factory descriptors
718 Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
719 if (!Descriptor->Factory.KsPinDescriptor)
720 goto cleanup;
721
722 // allocate pin instance info
723 Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
724 if (!Descriptor->Factory.Instances)
725 goto cleanup;
726
727 // initialize pin factory descriptor
728 Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
729 Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
730
731 // grab first entry
732 SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
733
734 // copy pin factories
735 for(Index = 0; Index < FilterDescription->PinCount; Index++)
736 {
737 // copy pin descriptor
738 RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
739
740 // initialize pin factory instance data
741 Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
742 Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
743 Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
744 Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
745
746 // check if the descriptor has an automation table
747 if (SrcDescriptor->AutomationTable)
748 {
749 // it has, grab first entry
750 PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
751
752 // now add all supported property items
753 for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
754 {
755 // add the property item to the table
756 Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
757
758 // check for success
759 if (Status != STATUS_SUCCESS)
760 {
761 // goto cleanup
762 goto cleanup;
763 }
764
765 // move to next entry
766 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
767 }
768 }
769
770 // move to next entry
771 SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
772 }
773 }
774
775 // allocate topology descriptor
776 Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
777 if (!Descriptor->Topology)
778 goto cleanup;
779
780 // are there any connections
781 if (FilterDescription->ConnectionCount)
782 {
783 // allocate connection descriptor
784 Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
785 if (!Descriptor->Topology->TopologyConnections)
786 goto cleanup;
787
788 // copy connection descriptor
789 RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
790
791 // store connection count
792 Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
793 }
794
795 // does the filter have nodes
796 if (FilterDescription->NodeCount)
797 {
798 // allocate topology node types array
799 Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
800 if (!Descriptor->Topology->TopologyNodes)
801 goto cleanup;
802
803 // allocate topology node names array
804 Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
805 if (!Descriptor->Topology->TopologyNodesNames)
806 goto cleanup;
807
808 // grab first entry
809 NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
810
811 // iterate all nodes and copy node types / names and node properties
812 for(Index = 0; Index < FilterDescription->NodeCount; Index++)
813 {
814 // does it have a type
815 if (NodeDescriptor->Type)
816 {
817 // copy node type
818 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
819 }
820
821 // does it have a node name
822 if (NodeDescriptor->Name)
823 {
824 // copy node name
825 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
826 }
827
828 // check if has an automation table
829 if (NodeDescriptor->AutomationTable)
830 {
831 // grab first entry
832 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
833
834 // copy all node properties into the global property set
835 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
836 {
837 // add to property set
838 Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
839
840 // check for success
841 if (Status != STATUS_SUCCESS)
842 {
843 // failed
844 goto cleanup;
845 }
846
847 // move to next property item
848 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
849 }
850 }
851
852 // move to next descriptor
853 NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
854 }
855
856 // now store the topology node count
857 Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
858 }
859
860 // store descriptor
861 Descriptor->DeviceDescriptor = FilterDescription;
862
863 // store result
864 *OutSubdeviceDescriptor = Descriptor;
865 // done
866 return STATUS_SUCCESS;
867
868 cleanup:
869 if (Descriptor)
870 {
871 if (Descriptor->Interfaces)
872 FreeItem(Descriptor->Interfaces, TAG_PORTCLASS);
873
874 if (Descriptor->Factory.KsPinDescriptor)
875 FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS);
876
877 FreeItem(Descriptor, TAG_PORTCLASS);
878 }
879 return Status;
880 }
881
882 NTSTATUS
883 NTAPI
884 PcValidateConnectRequest(
885 IN PIRP Irp,
886 IN KSPIN_FACTORY * Factory,
887 OUT PKSPIN_CONNECT * Connect)
888 {
889 return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect);
890 }
891