- Copy Filter descriptor for each instantiated filter
[reactos.git] / reactos / drivers / ksfilter / ks / filter.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/filter.c
5 * PURPOSE: KS IKsFilter interface functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 typedef struct
13 {
14 KSBASIC_HEADER Header;
15 KSFILTER Filter;
16
17 IKsFilterVtbl *lpVtbl;
18 IKsControlVtbl *lpVtblKsControl;
19 IKsFilterFactory * FilterFactory;
20 LONG ref;
21
22 PKSIOBJECT_HEADER ObjectHeader;
23 KSTOPOLOGY Topology;
24 KSPIN_DESCRIPTOR * PinDescriptors;
25 ULONG PinDescriptorCount;
26 PKSFILTERFACTORY Factory;
27 PFILE_OBJECT FileObject;
28 KMUTEX ProcessingMutex;
29
30
31 PFNKSFILTERPOWER Sleep;
32 PFNKSFILTERPOWER Wake;
33
34 ULONG *PinInstanceCount;
35 }IKsFilterImpl;
36
37 const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
38 const GUID IID_IKsFilter = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
39 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
40 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
41
42
43 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, KspTopologyPropertyHandler);
44 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, KspPinPropertyHandler, KspPinPropertyHandler, KspPinPropertyHandler);
45
46 KSPROPERTY_SET FilterPropertySet[] =
47 {
48 {
49 &KSPROPSETID_Topology,
50 sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
51 (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
52 0,
53 NULL
54 },
55 {
56 &KSPROPSETID_Pin,
57 sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
58 (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
59 0,
60 NULL
61 }
62 };
63
64 NTSTATUS
65 NTAPI
66 IKsControl_fnQueryInterface(
67 IKsControl * iface,
68 IN REFIID refiid,
69 OUT PVOID* Output)
70 {
71 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
72
73 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
74 {
75 *Output = &This->lpVtbl;
76 _InterlockedIncrement(&This->ref);
77 return STATUS_SUCCESS;
78 }
79 return STATUS_UNSUCCESSFUL;
80 }
81
82 ULONG
83 NTAPI
84 IKsControl_fnAddRef(
85 IKsControl * iface)
86 {
87 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
88
89 return InterlockedIncrement(&This->ref);
90 }
91
92 ULONG
93 NTAPI
94 IKsControl_fnRelease(
95 IKsControl * iface)
96 {
97 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
98
99 InterlockedDecrement(&This->ref);
100
101 /* Return new reference count */
102 return This->ref;
103 }
104
105 NTSTATUS
106 NTAPI
107 IKsControl_fnKsProperty(
108 IKsControl * iface,
109 IN PKSPROPERTY Property,
110 IN ULONG PropertyLength,
111 IN OUT PVOID PropertyData,
112 IN ULONG DataLength,
113 OUT ULONG* BytesReturned)
114 {
115 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
116
117 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
118 }
119
120
121 NTSTATUS
122 NTAPI
123 IKsControl_fnKsMethod(
124 IKsControl * iface,
125 IN PKSMETHOD Method,
126 IN ULONG MethodLength,
127 IN OUT PVOID MethodData,
128 IN ULONG DataLength,
129 OUT ULONG* BytesReturned)
130 {
131 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
132
133 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
134 }
135
136
137 NTSTATUS
138 NTAPI
139 IKsControl_fnKsEvent(
140 IKsControl * iface,
141 IN PKSEVENT Event OPTIONAL,
142 IN ULONG EventLength,
143 IN OUT PVOID EventData,
144 IN ULONG DataLength,
145 OUT ULONG* BytesReturned)
146 {
147 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
148
149 if (Event)
150 {
151 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
152 }
153 else
154 {
155 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
156 }
157
158 }
159
160 static IKsControlVtbl vt_IKsControl =
161 {
162 IKsControl_fnQueryInterface,
163 IKsControl_fnAddRef,
164 IKsControl_fnRelease,
165 IKsControl_fnKsProperty,
166 IKsControl_fnKsMethod,
167 IKsControl_fnKsEvent
168 };
169
170
171 NTSTATUS
172 NTAPI
173 IKsFilter_fnQueryInterface(
174 IKsFilter * iface,
175 IN REFIID refiid,
176 OUT PVOID* Output)
177 {
178 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
179
180 if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
181 IsEqualGUIDAligned(refiid, &IID_IKsFilter))
182 {
183 *Output = &This->lpVtbl;
184 _InterlockedIncrement(&This->ref);
185 return STATUS_SUCCESS;
186 }
187 else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
188 {
189 *Output = &This->lpVtblKsControl;
190 _InterlockedIncrement(&This->ref);
191 return STATUS_SUCCESS;
192 }
193
194 return STATUS_UNSUCCESSFUL;
195 }
196
197 ULONG
198 NTAPI
199 IKsFilter_fnAddRef(
200 IKsFilter * iface)
201 {
202 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
203
204 return InterlockedIncrement(&This->ref);
205 }
206
207 ULONG
208 NTAPI
209 IKsFilter_fnRelease(
210 IKsFilter * iface)
211 {
212 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
213
214 InterlockedDecrement(&This->ref);
215
216 if (This->ref == 0)
217 {
218 FreeItem(This);
219 return 0;
220 }
221 /* Return new reference count */
222 return This->ref;
223
224 }
225
226 PKSFILTER
227 NTAPI
228 IKsFilter_fnGetStruct(
229 IKsFilter * iface)
230 {
231 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
232
233 return &This->Filter;
234 }
235
236 BOOL
237 NTAPI
238 IKsFilter_fnDoAllNecessaryPinsExist(
239 IKsFilter * iface)
240 {
241 UNIMPLEMENTED
242 return FALSE;
243 }
244
245 NTSTATUS
246 NTAPI
247 IKsFilter_fnCreateNode(
248 IKsFilter * iface,
249 IN PIRP Irp,
250 IN IKsPin * Pin,
251 IN PLIST_ENTRY ListEntry)
252 {
253 UNIMPLEMENTED
254 return STATUS_NOT_IMPLEMENTED;
255 }
256
257 NTSTATUS
258 NTAPI
259 IKsFilter_fnBindProcessPinsToPipeSection(
260 IKsFilter * iface,
261 IN struct KSPROCESSPIPESECTION *Section,
262 IN PVOID Create,
263 IN PKSPIN KsPin,
264 OUT IKsPin **Pin,
265 OUT PKSGATE *OutGate)
266 {
267 UNIMPLEMENTED
268 return STATUS_NOT_IMPLEMENTED;
269 }
270
271 NTSTATUS
272 NTAPI
273 IKsFilter_fnUnbindProcessPinsFromPipeSection(
274 IKsFilter * iface,
275 IN struct KSPROCESSPIPESECTION *Section)
276 {
277 UNIMPLEMENTED
278 return STATUS_NOT_IMPLEMENTED;
279 }
280
281 NTSTATUS
282 NTAPI
283 IKsFilter_fnAddProcessPin(
284 IKsFilter * iface,
285 IN PKSPROCESSPIN ProcessPin)
286 {
287 UNIMPLEMENTED
288 return STATUS_NOT_IMPLEMENTED;
289 }
290
291 NTSTATUS
292 NTAPI
293 IKsFilter_fnRemoveProcessPin(
294 IKsFilter * iface,
295 IN PKSPROCESSPIN ProcessPin)
296 {
297 UNIMPLEMENTED
298 return STATUS_NOT_IMPLEMENTED;
299 }
300
301 BOOL
302 NTAPI
303 IKsFilter_fnReprepareProcessPipeSection(
304 IKsFilter * iface,
305 IN struct KSPROCESSPIPESECTION *PipeSection,
306 IN PULONG Data)
307 {
308 UNIMPLEMENTED
309 return FALSE;
310 }
311
312 VOID
313 NTAPI
314 IKsFilter_fnDeliverResetState(
315 IKsFilter * iface,
316 IN struct KSPROCESSPIPESECTION *PipeSection,
317 IN KSRESET ResetState)
318 {
319 UNIMPLEMENTED
320 }
321
322 BOOL
323 NTAPI
324 IKsFilter_fnIsFrameHolding(
325 IKsFilter * iface)
326 {
327 UNIMPLEMENTED
328 return FALSE;
329 }
330
331 VOID
332 NTAPI
333 IKsFilter_fnRegisterForCopyCallbacks(
334 IKsFilter * iface,
335 IKsQueue *Queue,
336 BOOL Register)
337 {
338 UNIMPLEMENTED
339 }
340
341 PKSPROCESSPIN_INDEXENTRY
342 NTAPI
343 IKsFilter_fnGetProcessDispatch(
344 IKsFilter * iface)
345 {
346 UNIMPLEMENTED
347 return NULL;
348 }
349
350 static IKsFilterVtbl vt_IKsFilter =
351 {
352 IKsFilter_fnQueryInterface,
353 IKsFilter_fnAddRef,
354 IKsFilter_fnRelease,
355 IKsFilter_fnGetStruct,
356 IKsFilter_fnDoAllNecessaryPinsExist,
357 IKsFilter_fnCreateNode,
358 IKsFilter_fnBindProcessPinsToPipeSection,
359 IKsFilter_fnUnbindProcessPinsFromPipeSection,
360 IKsFilter_fnAddProcessPin,
361 IKsFilter_fnRemoveProcessPin,
362 IKsFilter_fnReprepareProcessPipeSection,
363 IKsFilter_fnDeliverResetState,
364 IKsFilter_fnIsFrameHolding,
365 IKsFilter_fnRegisterForCopyCallbacks,
366 IKsFilter_fnGetProcessDispatch
367 };
368
369 NTSTATUS
370 IKsFilter_GetFilterFromIrp(
371 IN PIRP Irp,
372 OUT IKsFilter **Filter)
373 {
374 PIO_STACK_LOCATION IoStack;
375 PKSIOBJECT_HEADER ObjectHeader;
376 NTSTATUS Status;
377
378 /* get current irp stack */
379 IoStack = IoGetCurrentIrpStackLocation(Irp);
380
381 /* santiy check */
382 ASSERT(IoStack->FileObject != NULL);
383
384 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
385
386 /* sanity is important */
387 ASSERT(ObjectHeader != NULL);
388 ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
389 ASSERT(ObjectHeader->Unknown != NULL);
390
391 /* get our private interface */
392 Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
393
394 if (!NT_SUCCESS(Status))
395 {
396 /* something is wrong here */
397 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
398 Irp->IoStatus.Status = Status;
399
400 /* complete and forget irp */
401 IoCompleteRequest(Irp, IO_NO_INCREMENT);
402 return Status;
403 }
404 return Status;
405 }
406
407
408 NTSTATUS
409 NTAPI
410 IKsFilter_DispatchClose(
411 IN PDEVICE_OBJECT DeviceObject,
412 IN PIRP Irp)
413 {
414 IKsFilter * Filter;
415 IKsFilterImpl * This;
416 NTSTATUS Status;
417
418 /* obtain filter from object header */
419 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
420 if (!NT_SUCCESS(Status))
421 return Status;
422
423 /* get our real implementation */
424 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl);
425
426 /* does the driver support notifications */
427 if (This->Factory->FilterDescriptor && This->Factory->FilterDescriptor->Dispatch && This->Factory->FilterDescriptor->Dispatch->Close)
428 {
429 /* call driver's filter close function */
430 Status = This->Factory->FilterDescriptor->Dispatch->Close(&This->Filter, Irp);
431 }
432
433 if (Status != STATUS_PENDING)
434 {
435 /* save the result */
436 Irp->IoStatus.Status = Status;
437 /* complete irp */
438 IoCompleteRequest(Irp, IO_NO_INCREMENT);
439
440 /* remove our instance from the filter factory */
441 This->FilterFactory->lpVtbl->RemoveFilterInstance(This->FilterFactory, Filter);
442
443 /* now release the acquired interface */
444 Filter->lpVtbl->Release(Filter);
445
446 /* free object header */
447 KsFreeObjectHeader(This->ObjectHeader);
448 }
449
450 /* done */
451 return Status;
452 }
453
454 NTSTATUS
455 KspHandlePropertyInstances(
456 IN PIO_STATUS_BLOCK IoStatus,
457 IN PKSIDENTIFIER Request,
458 IN OUT PVOID Data,
459 IN IKsFilterImpl * This,
460 IN BOOL Global)
461 {
462 KSPIN_CINSTANCES * Instances;
463 KSP_PIN * Pin = (KSP_PIN*)Request;
464
465 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
466 {
467 /* no filter / pin descriptor */
468 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
469 return STATUS_NOT_IMPLEMENTED;
470 }
471
472 /* ignore custom structs for now */
473 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
474 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
475
476 Instances = (KSPIN_CINSTANCES*)Data;
477 /* max instance count */
478 Instances->PossibleCount = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible;
479 /* current instance count */
480 Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
481
482 IoStatus->Information = sizeof(KSPIN_CINSTANCES);
483 IoStatus->Status = STATUS_SUCCESS;
484 return STATUS_SUCCESS;
485 }
486
487 NTSTATUS
488 KspHandleNecessaryPropertyInstances(
489 IN PIO_STATUS_BLOCK IoStatus,
490 IN PKSIDENTIFIER Request,
491 IN OUT PVOID Data,
492 IN IKsFilterImpl * This)
493 {
494 PULONG Result;
495 KSP_PIN * Pin = (KSP_PIN*)Request;
496
497 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
498 {
499 /* no filter / pin descriptor */
500 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
501 return STATUS_NOT_IMPLEMENTED;
502 }
503
504 /* ignore custom structs for now */
505 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
506 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
507
508 Result = (PULONG)Data;
509 *Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
510
511 IoStatus->Information = sizeof(ULONG);
512 IoStatus->Status = STATUS_SUCCESS;
513 return STATUS_SUCCESS;
514 }
515
516 NTSTATUS
517 KspHandleDataIntersection(
518 IN PIRP Irp,
519 IN PIO_STATUS_BLOCK IoStatus,
520 IN PKSIDENTIFIER Request,
521 IN OUT PVOID Data,
522 IN ULONG DataLength,
523 IN IKsFilterImpl * This)
524 {
525 PKSMULTIPLE_ITEM MultipleItem;
526 PKSDATARANGE DataRange;
527 NTSTATUS Status = STATUS_NO_MATCH;
528 ULONG Index, Length;
529 KSP_PIN * Pin = (KSP_PIN*)Request;
530
531 /* Access parameters */
532 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
533 DataRange = (PKSDATARANGE)(MultipleItem + 1);
534
535 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
536 {
537 /* no filter / pin descriptor */
538 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
539 return STATUS_NOT_IMPLEMENTED;
540 }
541
542 /* ignore custom structs for now */
543 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
544 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
545
546 if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
547 This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
548 This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
549 {
550 /* no driver supported intersect handler / no provided data ranges */
551 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
552 return STATUS_NOT_IMPLEMENTED;
553 }
554
555 for(Index = 0; Index < MultipleItem->Count; Index++)
556 {
557 /* Call miniport's properitary handler */
558 Status = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler(NULL, /* context */
559 Irp,
560 Pin,
561 DataRange,
562 (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges,
563 DataLength,
564 Data,
565 &Length);
566
567 if (Status == STATUS_SUCCESS)
568 {
569 IoStatus->Information = Length;
570 break;
571 }
572 DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
573 }
574
575 IoStatus->Status = Status;
576 return Status;
577 }
578
579 NTSTATUS
580 NTAPI
581 KspPinPropertyHandler(
582 IN PIRP Irp,
583 IN PKSIDENTIFIER Request,
584 IN OUT PVOID Data)
585 {
586 PIO_STACK_LOCATION IoStack;
587 IKsFilterImpl * This;
588 NTSTATUS Status = STATUS_UNSUCCESSFUL;
589
590 /* get filter implementation */
591 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
592
593 /* get current stack location */
594 IoStack = IoGetCurrentIrpStackLocation(Irp);
595
596 switch(Request->Id)
597 {
598 case KSPROPERTY_PIN_CTYPES:
599 case KSPROPERTY_PIN_DATAFLOW:
600 case KSPROPERTY_PIN_DATARANGES:
601 case KSPROPERTY_PIN_INTERFACES:
602 case KSPROPERTY_PIN_MEDIUMS:
603 case KSPROPERTY_PIN_COMMUNICATION:
604 case KSPROPERTY_PIN_CATEGORY:
605 case KSPROPERTY_PIN_NAME:
606 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
607 Status = KsPinPropertyHandler(Irp, Request, Data, This->PinDescriptorCount, This->PinDescriptors);
608 break;
609 case KSPROPERTY_PIN_GLOBALCINSTANCES:
610 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
611 break;
612 case KSPROPERTY_PIN_CINSTANCES:
613 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
614 break;
615 case KSPROPERTY_PIN_NECESSARYINSTANCES:
616 Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
617 break;
618
619 case KSPROPERTY_PIN_DATAINTERSECTION:
620 Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
621 break;
622 case KSPROPERTY_PIN_PHYSICALCONNECTION:
623 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
624 UNIMPLEMENTED
625 Status = STATUS_NOT_IMPLEMENTED;
626 break;
627 default:
628 UNIMPLEMENTED
629 Status = STATUS_UNSUCCESSFUL;
630 }
631
632 return Status;
633 }
634
635 NTSTATUS
636 FindPropertyHandler(
637 IN PIO_STATUS_BLOCK IoStatus,
638 IN KSPROPERTY_SET * FilterPropertySet,
639 IN ULONG FilterPropertySetCount,
640 IN PKSPROPERTY Property,
641 IN ULONG InputBufferLength,
642 IN ULONG OutputBufferLength,
643 OUT PFNKSHANDLER *PropertyHandler)
644 {
645 ULONG Index, ItemIndex;
646
647 for(Index = 0; Index < FilterPropertySetCount; Index++)
648 {
649 if (IsEqualGUIDAligned(&Property->Set, FilterPropertySet[Index].Set))
650 {
651 for(ItemIndex = 0; ItemIndex < FilterPropertySet[Index].PropertiesCount; ItemIndex++)
652 {
653 if (FilterPropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
654 {
655 if (Property->Flags & KSPROPERTY_TYPE_SET)
656 *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
657
658 if (Property->Flags & KSPROPERTY_TYPE_GET)
659 *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
660
661 if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
662 {
663 /* too small input buffer */
664 IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty;
665 IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
666 return STATUS_BUFFER_TOO_SMALL;
667 }
668
669 if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
670 {
671 /* too small output buffer */
672 IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinData;
673 IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
674 return STATUS_BUFFER_TOO_SMALL;
675 }
676 return STATUS_SUCCESS;
677 }
678 }
679 }
680 }
681 return STATUS_UNSUCCESSFUL;
682 }
683
684
685
686 NTSTATUS
687 NTAPI
688 IKsFilter_DispatchDeviceIoControl(
689 IN PDEVICE_OBJECT DeviceObject,
690 IN PIRP Irp)
691 {
692 PIO_STACK_LOCATION IoStack;
693 PFNKSHANDLER PropertyHandler = NULL;
694 IKsFilter * Filter;
695 IKsFilterImpl * This;
696 NTSTATUS Status;
697
698 /* obtain filter from object header */
699 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
700 if (!NT_SUCCESS(Status))
701 return Status;
702
703 /* get our real implementation */
704 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl);
705
706 /* current irp stack */
707 IoStack = IoGetCurrentIrpStackLocation(Irp);
708
709 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
710 {
711 UNIMPLEMENTED;
712
713 /* release filter interface */
714 Filter->lpVtbl->Release(Filter);
715
716 /* complete and forget irp */
717 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
718 IoCompleteRequest(Irp, IO_NO_INCREMENT);
719 return STATUS_NOT_IMPLEMENTED;
720 }
721
722 /* find a supported property handler */
723 Status = FindPropertyHandler(&Irp->IoStatus, FilterPropertySet, 2, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
724 if (NT_SUCCESS(Status))
725 {
726 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)This;
727 DPRINT("Calling property handler %p\n", PropertyHandler);
728 Status = PropertyHandler(Irp, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, Irp->UserBuffer);
729 }
730 else
731 {
732 /* call driver's property handler */
733 UNIMPLEMENTED
734 Status = STATUS_NOT_IMPLEMENTED;
735 }
736
737 Irp->IoStatus.Status = Status;
738 IoCompleteRequest(Irp, IO_NO_INCREMENT);
739
740 /* done */
741 return Status;
742 }
743
744 static KSDISPATCH_TABLE DispatchTable =
745 {
746 IKsFilter_DispatchDeviceIoControl,
747 KsDispatchInvalidDeviceRequest,
748 KsDispatchInvalidDeviceRequest,
749 KsDispatchInvalidDeviceRequest,
750 IKsFilter_DispatchClose,
751 KsDispatchQuerySecurity,
752 KsDispatchSetSecurity,
753 KsDispatchFastIoDeviceControlFailure,
754 KsDispatchFastReadFailure,
755 KsDispatchFastReadFailure,
756 };
757
758
759 NTSTATUS
760 IKsFilter_CreateDescriptors(
761 IKsFilterImpl * This,
762 KSFILTER_DESCRIPTOR* FilterDescriptor)
763 {
764 ULONG Index = 0;
765
766 /* initialize pin descriptors */
767 if (FilterDescriptor->PinDescriptorsCount)
768 {
769 /* allocate pin instance count array */
770 This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount);
771 if(!This->PinDescriptors)
772 {
773 return STATUS_INSUFFICIENT_RESOURCES;
774 }
775
776 /* allocate pin descriptor array */
777 This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount);
778 if(!This->PinDescriptors)
779 {
780 FreeItem(This->PinInstanceCount);
781 return STATUS_INSUFFICIENT_RESOURCES;
782 }
783
784 /* set pin count */
785 This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
786 /* now copy those pin descriptors over */
787 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
788 {
789 /* copy one pin per time */
790 RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
791 }
792 }
793
794 /* initialize topology descriptor */
795 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
796 This->Topology.Categories = FilterDescriptor->Categories;
797 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
798 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
799 This->Topology.TopologyConnections = FilterDescriptor->Connections;
800
801 if (This->Topology.TopologyNodesCount > 0)
802 {
803 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
804 /* allocate topology node types array */
805 if (!This->Topology.TopologyNodes)
806 return STATUS_INSUFFICIENT_RESOURCES;
807
808 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
809 /* allocate topology names array */
810 if (!This->Topology.TopologyNodesNames)
811 {
812 FreeItem((PVOID)This->Topology.TopologyNodes);
813 return STATUS_INSUFFICIENT_RESOURCES;
814 }
815
816 for(Index = 0; Index < This->Topology.TopologyNodesCount; Index++)
817 {
818 /* copy topology type */
819 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
820 /* copy topology name */
821 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
822 }
823 }
824
825 /* done! */
826 return STATUS_SUCCESS;
827 }
828
829 NTSTATUS
830 IKsFilter_CopyFilterDescriptor(
831 IKsFilterImpl * This,
832 const KSFILTER_DESCRIPTOR* FilterDescriptor)
833 {
834 This->Filter.Descriptor = (const KSFILTER_DESCRIPTOR*)AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
835 if (!This->Filter.Descriptor)
836 return STATUS_INSUFFICIENT_RESOURCES;
837
838 /* copy all fields */
839 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
840
841
842 /* perform deep copy of pin descriptors */
843 if (FilterDescriptor->PinDescriptorsCount)
844 {
845 KSPIN_DESCRIPTOR_EX * PinDescriptors = (KSPIN_DESCRIPTOR_EX *)AllocateItem(NonPagedPool, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
846
847
848 if (!PinDescriptors)
849 {
850 FreeItem((PVOID)This->Filter.Descriptor);
851 return STATUS_INSUFFICIENT_RESOURCES;
852 }
853 RtlMoveMemory((PVOID)PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
854
855 /* brain-dead gcc hack */
856 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptors, sizeof(PKSPIN_DESCRIPTOR_EX));
857
858 }
859
860 /* perform deep copy of node descriptors */
861 if (FilterDescriptor->NodeDescriptorsCount)
862 {
863 KSNODE_DESCRIPTOR* NodeDescriptor = AllocateItem(NonPagedPool, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
864 if (!NodeDescriptor)
865 {
866 if (This->Filter.Descriptor->PinDescriptors)
867 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
868 FreeItem((PVOID)This->Filter.Descriptor);
869 return STATUS_INSUFFICIENT_RESOURCES;
870 }
871 RtlMoveMemory((PVOID)NodeDescriptor, FilterDescriptor->NodeDescriptors, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
872
873 /* brain-dead gcc hack */
874 RtlMoveMemory((PVOID)&This->Filter.Descriptor->NodeDescriptors, NodeDescriptor, sizeof(PKSNODE_DESCRIPTOR));
875 }
876
877 /* perform deep copy of connections descriptors */
878 if (FilterDescriptor->NodeDescriptorsCount)
879 {
880 KSTOPOLOGY_CONNECTION* Connections = AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
881 if (!Connections)
882 {
883 if (This->Filter.Descriptor->PinDescriptors)
884 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
885
886 if (This->Filter.Descriptor->NodeDescriptors)
887 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
888
889 FreeItem((PVOID)This->Filter.Descriptor);
890 return STATUS_INSUFFICIENT_RESOURCES;
891 }
892
893 RtlMoveMemory((PVOID)Connections, FilterDescriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
894
895 /* brain-dead gcc hack */
896 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(PKSTOPOLOGY_CONNECTION));
897 }
898
899 return STATUS_SUCCESS;
900 }
901
902
903 NTSTATUS
904 NTAPI
905 KspCreateFilter(
906 IN PDEVICE_OBJECT DeviceObject,
907 IN PIRP Irp,
908 IN IKsFilterFactory *iface)
909 {
910 IKsFilterImpl * This;
911 IKsDevice *KsDevice;
912 PKSFILTERFACTORY Factory;
913 PIO_STACK_LOCATION IoStack;
914 PDEVICE_EXTENSION DeviceExtension;
915 NTSTATUS Status;
916
917 /* get device extension */
918 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
919
920 /* get the filter factory */
921 Factory = iface->lpVtbl->GetStruct(iface);
922
923 if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
924 {
925 /* Sorry it just will not work */
926 return STATUS_UNSUCCESSFUL;
927 }
928
929 /* allocate filter instance */
930 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory));
931 if (!This)
932 return STATUS_INSUFFICIENT_RESOURCES;
933
934 /* copy filter descriptor */
935 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
936 if (!NT_SUCCESS(Status))
937 {
938 /* not enough memory */
939 FreeItem(This);
940 return STATUS_INSUFFICIENT_RESOURCES;
941 }
942
943 /* get current irp stack */
944 IoStack = IoGetCurrentIrpStackLocation(Irp);
945
946
947 /* initialize object bag */
948 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
949 if (!This->Filter.Bag)
950 {
951 /* no memory */
952 FreeItem(This);
953 return STATUS_INSUFFICIENT_RESOURCES;
954 }
955
956
957
958 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
959 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
960
961 /* initialize filter instance */
962 This->ref = 1;
963 This->lpVtbl = &vt_IKsFilter;
964 This->lpVtblKsControl = &vt_IKsControl;
965
966 This->Filter.Descriptor = Factory->FilterDescriptor;
967 This->Factory = Factory;
968 This->FilterFactory = iface;
969 This->FileObject = IoStack->FileObject;
970 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
971 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
972 This->Header.Type = KsObjectTypeFilter;
973 KeInitializeMutex(&This->ProcessingMutex, 0);
974
975
976 /* allocate the stream descriptors */
977 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
978 if (!NT_SUCCESS(Status))
979 {
980 /* what can go wrong, goes wrong */
981 FreeItem(This);
982 return Status;
983 }
984
985 /* now add the filter instance to the filter factory */
986 Status = iface->lpVtbl->AddFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
987
988 if (!NT_SUCCESS(Status))
989 {
990 /* failed to add filter */
991 FreeItem(This);
992
993 return Status;
994 }
995
996 /* now let driver initialize the filter instance */
997 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
998
999 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1000 {
1001 /* driver failed to initialize */
1002 DPRINT1("Driver: Status %x\n", Status);
1003
1004 /* remove filter instance from filter factory */
1005 iface->lpVtbl->RemoveFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
1006
1007 /* free filter instance */
1008 FreeItem(This);
1009
1010 return Status;
1011 }
1012
1013 /* now allocate the object header */
1014 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 0, NULL, Irp, &DispatchTable);
1015 if (!NT_SUCCESS(Status))
1016 {
1017 /* failed to allocate object header */
1018 DPRINT1("Failed to allocate object header %x\n", Status);
1019
1020 return Status;
1021 }
1022
1023 /* initialize object header */
1024 This->Header.Type = KsObjectTypeFilter;
1025 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1026 This->ObjectHeader->Type = KsObjectTypeFilter;
1027 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1028 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1029
1030
1031 /* completed initialization */
1032 return Status;
1033 }
1034
1035 /*
1036 @implemented
1037 */
1038 KSDDKAPI
1039 VOID
1040 NTAPI
1041 KsFilterAcquireProcessingMutex(
1042 IN PKSFILTER Filter)
1043 {
1044 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1045
1046 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1047 }
1048
1049 /*
1050 @implemented
1051 */
1052 KSDDKAPI
1053 VOID
1054 NTAPI
1055 KsFilterReleaseProcessingMutex(
1056 IN PKSFILTER Filter)
1057 {
1058 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1059
1060 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1061 }
1062
1063 /*
1064 @implemented
1065 */
1066 KSDDKAPI
1067 NTSTATUS
1068 NTAPI
1069 KsFilterAddTopologyConnections (
1070 IN PKSFILTER Filter,
1071 IN ULONG NewConnectionsCount,
1072 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1073 {
1074 ULONG Count;
1075 KSTOPOLOGY_CONNECTION * Connections;
1076 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1077
1078 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1079
1080 /* allocate array */
1081 Connections = AllocateItem(NonPagedPool, Count * sizeof(KSTOPOLOGY_CONNECTION));
1082 if (!Connections)
1083 return STATUS_INSUFFICIENT_RESOURCES;
1084
1085 /* FIXME verify connections */
1086
1087 if (This->Filter.Descriptor->ConnectionsCount)
1088 {
1089 /* copy old connections */
1090 RtlMoveMemory(Connections, This->Filter.Descriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * This->Filter.Descriptor->ConnectionsCount);
1091 }
1092
1093 /* add new connections */
1094 RtlMoveMemory((PVOID)(Connections + This->Filter.Descriptor->ConnectionsCount), NewTopologyConnections, NewConnectionsCount);
1095
1096 /* add the new connections */
1097 RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */
1098
1099 /* free old connections array */
1100 if (This->Filter.Descriptor->ConnectionsCount)
1101 {
1102 FreeItem((PVOID)This->Filter.Descriptor->Connections);
1103 }
1104
1105 /* brain-dead gcc hack */
1106 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*));
1107
1108 return STATUS_SUCCESS;
1109 }
1110
1111 /*
1112 @unimplemented
1113 */
1114 KSDDKAPI
1115 VOID
1116 NTAPI
1117 KsFilterAttemptProcessing(
1118 IN PKSFILTER Filter,
1119 IN BOOLEAN Asynchronous)
1120 {
1121 UNIMPLEMENTED
1122 }
1123
1124 /*
1125 @unimplemented
1126 */
1127 KSDDKAPI
1128 NTSTATUS
1129 NTAPI
1130 KsFilterCreateNode (
1131 IN PKSFILTER Filter,
1132 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1133 OUT PULONG NodeID)
1134 {
1135 UNIMPLEMENTED
1136 return STATUS_NOT_IMPLEMENTED;
1137 }
1138
1139 /*
1140 @implemented
1141 */
1142 KSDDKAPI
1143 NTSTATUS
1144 NTAPI
1145 KsFilterCreatePinFactory (
1146 IN PKSFILTER Filter,
1147 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1148 OUT PULONG PinID)
1149 {
1150 ULONG Count;
1151 ULONG *PinInstanceCount;
1152 KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
1153 KSPIN_DESCRIPTOR * PinDescriptors;
1154 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1155
1156 /* calculate existing count */
1157 Count = This->PinDescriptorCount + 1;
1158
1159 /* allocate pin descriptors array */
1160 PinDescriptorsEx = AllocateItem(NonPagedPool, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * Count);
1161 if (!PinDescriptorsEx)
1162 return STATUS_INSUFFICIENT_RESOURCES;
1163
1164 /* allocate pin instance count array */
1165 PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * Count);
1166 if (!PinInstanceCount)
1167 {
1168 /* not enough memory */
1169 FreeItem(PinDescriptorsEx);
1170 return STATUS_INSUFFICIENT_RESOURCES;
1171 }
1172
1173 /* allocate pin descriptor array for pin property handling */
1174 PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * Count);
1175 if (!PinDescriptors)
1176 {
1177 /* not enough memory */
1178 FreeItem(PinDescriptorsEx);
1179 FreeItem(PinInstanceCount);
1180 return STATUS_INSUFFICIENT_RESOURCES;
1181 }
1182
1183 /* now copy all fields */
1184 if (Count > 1)
1185 {
1186 /* copy old descriptors */
1187 RtlMoveMemory(PinDescriptorsEx, This->Filter.Descriptor->PinDescriptors, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount);
1188 RtlMoveMemory(PinInstanceCount, This->PinInstanceCount, This->PinDescriptorCount * sizeof(ULONG));
1189 RtlMoveMemory(PinDescriptors, This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * This->PinDescriptorCount);
1190
1191 /* now free old descriptors */
1192 FreeItem(This->PinInstanceCount);
1193 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
1194 FreeItem(This->PinDescriptors);
1195 }
1196
1197 /* add new pin factory */
1198 RtlMoveMemory((PVOID)((ULONG_PTR)PinDescriptorsEx + max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount), InPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1199 RtlMoveMemory((PVOID)(PinDescriptors + This->PinDescriptorCount), &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1200
1201 /* replace old descriptor by using a gcc-compliant hack */
1202 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX*));
1203 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptorsCount, &Count, sizeof(ULONG));
1204
1205 This->PinDescriptors = PinDescriptors;
1206 This->PinInstanceCount = PinInstanceCount;
1207
1208 /* store new pin id */
1209 *PinID = This->PinDescriptorCount;
1210
1211 /* increment pin descriptor count */
1212 This->PinDescriptorCount++;
1213
1214 return STATUS_SUCCESS;
1215
1216 }
1217
1218 /*
1219 @unimplemented
1220 */
1221 KSDDKAPI
1222 PKSGATE
1223 NTAPI
1224 KsFilterGetAndGate(
1225 IN PKSFILTER Filter)
1226 {
1227 UNIMPLEMENTED
1228 return NULL;
1229 }
1230
1231 /*
1232 @implemented
1233 */
1234 KSDDKAPI
1235 ULONG
1236 NTAPI
1237 KsFilterGetChildPinCount(
1238 IN PKSFILTER Filter,
1239 IN ULONG PinId)
1240 {
1241 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1242
1243 if (PinId >= This->PinDescriptorCount)
1244 {
1245 /* index is out of bounds */
1246 return 0;
1247 }
1248 /* return pin instance count */
1249 return This->PinInstanceCount[PinId];
1250 }
1251
1252 /*
1253 @unimplemented
1254 */
1255 KSDDKAPI
1256 PKSPIN
1257 NTAPI
1258 KsFilterGetFirstChildPin(
1259 IN PKSFILTER Filter,
1260 IN ULONG PinId)
1261 {
1262 UNIMPLEMENTED
1263 return NULL;
1264 }
1265
1266 /*
1267 @implemented
1268 */
1269 KSDDKAPI
1270 VOID
1271 NTAPI
1272 KsFilterRegisterPowerCallbacks(
1273 IN PKSFILTER Filter,
1274 IN PFNKSFILTERPOWER Sleep OPTIONAL,
1275 IN PFNKSFILTERPOWER Wake OPTIONAL)
1276 {
1277 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1278
1279 This->Sleep = Sleep;
1280 This->Wake = Wake;
1281 }
1282
1283 /*
1284 @implemented
1285 */
1286 KSDDKAPI
1287 PKSFILTER
1288 NTAPI
1289 KsGetFilterFromIrp(
1290 IN PIRP Irp)
1291 {
1292 PIO_STACK_LOCATION IoStack;
1293 PKSIOBJECT_HEADER ObjectHeader;
1294
1295 /* get current irp stack location */
1296 IoStack = IoGetCurrentIrpStackLocation(Irp);
1297
1298 /* sanity check */
1299 ASSERT(IoStack->FileObject);
1300
1301 /* get object header */
1302 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
1303
1304 if (ObjectHeader->Type == KsObjectTypeFilter)
1305 {
1306 /* irp is targeted at the filter */
1307 return (PKSFILTER)ObjectHeader->ObjectType;
1308 }
1309 else if (ObjectHeader->Type == KsObjectTypePin)
1310 {
1311 /* irp is for a pin */
1312 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
1313 }
1314 else
1315 {
1316 /* irp is unappropiate to retrieve a filter */
1317 return NULL;
1318 }
1319 }