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