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