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