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