Sync with trunk head (r49139)
[reactos.git] / 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 IKsControlVtbl *lpVtblKsControl;
18 IKsFilterFactory * FilterFactory;
19 LONG ref;
20
21 PKSIOBJECT_HEADER ObjectHeader;
22 KSTOPOLOGY Topology;
23 PKSFILTERFACTORY Factory;
24 PFILE_OBJECT FileObject;
25 KMUTEX ControlMutex;
26 KMUTEX ProcessingMutex;
27
28
29 PFNKSFILTERPOWER Sleep;
30 PFNKSFILTERPOWER Wake;
31
32 ULONG *PinInstanceCount;
33 PKSPIN * FirstPin;
34 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
35
36 }IKsFilterImpl;
37
38 const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
39 const GUID IID_IKsFilter = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
40 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
41 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
42
43 VOID
44 IKsFilter_RemoveFilterFromFilterFactory(
45 IKsFilterImpl * This,
46 PKSFILTERFACTORY FilterFactory);
47
48 NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
49 NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
50
51
52 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler);
53 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler);
54
55 KSPROPERTY_SET FilterPropertySet[] =
56 {
57 {
58 &KSPROPSETID_Topology,
59 sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
60 (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
61 0,
62 NULL
63 },
64 {
65 &KSPROPSETID_Pin,
66 sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
67 (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
68 0,
69 NULL
70 }
71 };
72
73 NTSTATUS
74 NTAPI
75 IKsControl_fnQueryInterface(
76 IKsControl * iface,
77 IN REFIID refiid,
78 OUT PVOID* Output)
79 {
80 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
81
82 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
83 {
84 *Output = &This->Header.OuterUnknown;
85 _InterlockedIncrement(&This->ref);
86 return STATUS_SUCCESS;
87 }
88 return STATUS_UNSUCCESSFUL;
89 }
90
91 ULONG
92 NTAPI
93 IKsControl_fnAddRef(
94 IKsControl * iface)
95 {
96 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
97
98 return InterlockedIncrement(&This->ref);
99 }
100
101 ULONG
102 NTAPI
103 IKsControl_fnRelease(
104 IKsControl * iface)
105 {
106 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
107
108 InterlockedDecrement(&This->ref);
109
110 /* Return new reference count */
111 return This->ref;
112 }
113
114 NTSTATUS
115 NTAPI
116 IKsControl_fnKsProperty(
117 IKsControl * iface,
118 IN PKSPROPERTY Property,
119 IN ULONG PropertyLength,
120 IN OUT PVOID PropertyData,
121 IN ULONG DataLength,
122 OUT ULONG* BytesReturned)
123 {
124 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
125
126 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
127 }
128
129
130 NTSTATUS
131 NTAPI
132 IKsControl_fnKsMethod(
133 IKsControl * iface,
134 IN PKSMETHOD Method,
135 IN ULONG MethodLength,
136 IN OUT PVOID MethodData,
137 IN ULONG DataLength,
138 OUT ULONG* BytesReturned)
139 {
140 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
141
142 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
143 }
144
145
146 NTSTATUS
147 NTAPI
148 IKsControl_fnKsEvent(
149 IKsControl * iface,
150 IN PKSEVENT Event OPTIONAL,
151 IN ULONG EventLength,
152 IN OUT PVOID EventData,
153 IN ULONG DataLength,
154 OUT ULONG* BytesReturned)
155 {
156 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
157
158 if (Event)
159 {
160 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
161 }
162 else
163 {
164 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
165 }
166
167 }
168
169 static IKsControlVtbl vt_IKsControl =
170 {
171 IKsControl_fnQueryInterface,
172 IKsControl_fnAddRef,
173 IKsControl_fnRelease,
174 IKsControl_fnKsProperty,
175 IKsControl_fnKsMethod,
176 IKsControl_fnKsEvent
177 };
178
179
180 NTSTATUS
181 NTAPI
182 IKsFilter_fnQueryInterface(
183 IKsFilter * iface,
184 IN REFIID refiid,
185 OUT PVOID* Output)
186 {
187 NTSTATUS Status;
188 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
189
190 if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
191 IsEqualGUIDAligned(refiid, &IID_IKsFilter))
192 {
193 *Output = &This->Header.OuterUnknown;
194 _InterlockedIncrement(&This->ref);
195 return STATUS_SUCCESS;
196 }
197 else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
198 {
199 *Output = &This->lpVtblKsControl;
200 _InterlockedIncrement(&This->ref);
201 return STATUS_SUCCESS;
202 }
203
204 if (This->Header.ClientAggregate)
205 {
206 /* using client aggregate */
207 Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
208
209 if (NT_SUCCESS(Status))
210 {
211 /* client aggregate supports interface */
212 return Status;
213 }
214 }
215
216 DPRINT("IKsFilter_fnQueryInterface no interface\n");
217 return STATUS_NOT_SUPPORTED;
218 }
219
220 ULONG
221 NTAPI
222 IKsFilter_fnAddRef(
223 IKsFilter * iface)
224 {
225 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
226
227 return InterlockedIncrement(&This->ref);
228 }
229
230 ULONG
231 NTAPI
232 IKsFilter_fnRelease(
233 IKsFilter * iface)
234 {
235 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
236
237 InterlockedDecrement(&This->ref);
238
239 if (This->ref == 0)
240 {
241 FreeItem(This);
242 return 0;
243 }
244 /* Return new reference count */
245 return This->ref;
246
247 }
248
249 PKSFILTER
250 NTAPI
251 IKsFilter_fnGetStruct(
252 IKsFilter * iface)
253 {
254 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
255
256 return &This->Filter;
257 }
258
259 BOOL
260 NTAPI
261 IKsFilter_fnDoAllNecessaryPinsExist(
262 IKsFilter * iface)
263 {
264 UNIMPLEMENTED
265 return FALSE;
266 }
267
268 NTSTATUS
269 NTAPI
270 IKsFilter_fnCreateNode(
271 IKsFilter * iface,
272 IN PIRP Irp,
273 IN IKsPin * Pin,
274 IN PLIST_ENTRY ListEntry)
275 {
276 UNIMPLEMENTED
277 return STATUS_NOT_IMPLEMENTED;
278 }
279
280 NTSTATUS
281 NTAPI
282 IKsFilter_fnBindProcessPinsToPipeSection(
283 IKsFilter * iface,
284 IN struct KSPROCESSPIPESECTION *Section,
285 IN PVOID Create,
286 IN PKSPIN KsPin,
287 OUT IKsPin **Pin,
288 OUT PKSGATE *OutGate)
289 {
290 UNIMPLEMENTED
291 return STATUS_NOT_IMPLEMENTED;
292 }
293
294 NTSTATUS
295 NTAPI
296 IKsFilter_fnUnbindProcessPinsFromPipeSection(
297 IKsFilter * iface,
298 IN struct KSPROCESSPIPESECTION *Section)
299 {
300 UNIMPLEMENTED
301 return STATUS_NOT_IMPLEMENTED;
302 }
303
304 NTSTATUS
305 NTAPI
306 IKsFilter_fnAddProcessPin(
307 IKsFilter * iface,
308 IN PKSPROCESSPIN ProcessPin)
309 {
310 NTSTATUS Status;
311 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
312
313 /* first acquire processing mutex */
314 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
315
316 /* sanity check */
317 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
318
319 /* allocate new process pin array */
320 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins,
321 (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PKSPROCESSPIN),
322 This->Filter.Descriptor->PinDescriptorsCount * sizeof(PKSPROCESSPIN),
323 0);
324
325 if (NT_SUCCESS(Status))
326 {
327 /* store process pin */
328 This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin;
329 This->ProcessPinIndex[ProcessPin->Pin->Id].Count++;
330 }
331
332 /* release process mutex */
333 KeReleaseMutex(&This->ProcessingMutex, FALSE);
334
335 return Status;
336 }
337
338 NTSTATUS
339 NTAPI
340 IKsFilter_fnRemoveProcessPin(
341 IKsFilter * iface,
342 IN PKSPROCESSPIN ProcessPin)
343 {
344 ULONG Index;
345 ULONG Count;
346 PKSPROCESSPIN * Pins;
347
348 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
349
350 /* first acquire processing mutex */
351 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
352
353 /* sanity check */
354 ASSERT(ProcessPin->Pin);
355 ASSERT(ProcessPin->Pin->Id);
356
357 Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
358 Pins = This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
359
360 /* search for current process pin */
361 for(Index = 0; Index < Count; Index++)
362 {
363 if (Pins[Index] == ProcessPin)
364 {
365 RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN));
366 break;
367 }
368
369 }
370
371 /* decrement pin count */
372 This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
373
374 if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
375 {
376 /* clear entry object bag will delete it */
377 This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
378 }
379
380 /* release process mutex */
381 KeReleaseMutex(&This->ProcessingMutex, FALSE);
382
383 /* done */
384 return STATUS_SUCCESS;
385 }
386
387 BOOL
388 NTAPI
389 IKsFilter_fnReprepareProcessPipeSection(
390 IKsFilter * iface,
391 IN struct KSPROCESSPIPESECTION *PipeSection,
392 IN PULONG Data)
393 {
394 UNIMPLEMENTED
395 return FALSE;
396 }
397
398 VOID
399 NTAPI
400 IKsFilter_fnDeliverResetState(
401 IKsFilter * iface,
402 IN struct KSPROCESSPIPESECTION *PipeSection,
403 IN KSRESET ResetState)
404 {
405 UNIMPLEMENTED
406 }
407
408 BOOL
409 NTAPI
410 IKsFilter_fnIsFrameHolding(
411 IKsFilter * iface)
412 {
413 UNIMPLEMENTED
414 return FALSE;
415 }
416
417 VOID
418 NTAPI
419 IKsFilter_fnRegisterForCopyCallbacks(
420 IKsFilter * iface,
421 IKsQueue *Queue,
422 BOOL Register)
423 {
424 UNIMPLEMENTED
425 }
426
427 PKSPROCESSPIN_INDEXENTRY
428 NTAPI
429 IKsFilter_fnGetProcessDispatch(
430 IKsFilter * iface)
431 {
432 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
433
434 return This->ProcessPinIndex;
435 }
436
437 static IKsFilterVtbl vt_IKsFilter =
438 {
439 IKsFilter_fnQueryInterface,
440 IKsFilter_fnAddRef,
441 IKsFilter_fnRelease,
442 IKsFilter_fnGetStruct,
443 IKsFilter_fnDoAllNecessaryPinsExist,
444 IKsFilter_fnCreateNode,
445 IKsFilter_fnBindProcessPinsToPipeSection,
446 IKsFilter_fnUnbindProcessPinsFromPipeSection,
447 IKsFilter_fnAddProcessPin,
448 IKsFilter_fnRemoveProcessPin,
449 IKsFilter_fnReprepareProcessPipeSection,
450 IKsFilter_fnDeliverResetState,
451 IKsFilter_fnIsFrameHolding,
452 IKsFilter_fnRegisterForCopyCallbacks,
453 IKsFilter_fnGetProcessDispatch
454 };
455
456 NTSTATUS
457 IKsFilter_GetFilterFromIrp(
458 IN PIRP Irp,
459 OUT IKsFilter **Filter)
460 {
461 PIO_STACK_LOCATION IoStack;
462 PKSIOBJECT_HEADER ObjectHeader;
463 NTSTATUS Status;
464
465 /* get current irp stack */
466 IoStack = IoGetCurrentIrpStackLocation(Irp);
467
468 /* santiy check */
469 ASSERT(IoStack->FileObject != NULL);
470
471 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
472
473 /* sanity is important */
474 ASSERT(ObjectHeader != NULL);
475 ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
476 ASSERT(ObjectHeader->Unknown != NULL);
477
478 /* get our private interface */
479 Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
480
481 if (!NT_SUCCESS(Status))
482 {
483 /* something is wrong here */
484 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
485 Irp->IoStatus.Status = Status;
486
487 /* complete and forget irp */
488 IoCompleteRequest(Irp, IO_NO_INCREMENT);
489 return Status;
490 }
491 return Status;
492 }
493
494
495 NTSTATUS
496 NTAPI
497 IKsFilter_DispatchClose(
498 IN PDEVICE_OBJECT DeviceObject,
499 IN PIRP Irp)
500 {
501 IKsFilter * Filter;
502 IKsFilterImpl * This;
503 NTSTATUS Status;
504
505 /* obtain filter from object header */
506 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
507 if (!NT_SUCCESS(Status))
508 return Status;
509
510 /* get our real implementation */
511 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
512
513 /* does the driver support notifications */
514 if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close)
515 {
516 /* call driver's filter close function */
517 Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp);
518 }
519
520 if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
521 {
522 /* save the result */
523 Irp->IoStatus.Status = Status;
524 /* complete irp */
525 IoCompleteRequest(Irp, IO_NO_INCREMENT);
526
527 /* remove our instance from the filter factory */
528 IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
529
530 /* free object header */
531 KsFreeObjectHeader(This->ObjectHeader);
532 }
533 else
534 {
535 /* complete and forget */
536 Irp->IoStatus.Status = Status;
537 /* complete irp */
538 IoCompleteRequest(Irp, IO_NO_INCREMENT);
539 }
540
541 /* done */
542 return Status;
543 }
544
545 NTSTATUS
546 KspHandlePropertyInstances(
547 IN PIO_STATUS_BLOCK IoStatus,
548 IN PKSIDENTIFIER Request,
549 IN OUT PVOID Data,
550 IN IKsFilterImpl * This,
551 IN BOOL Global)
552 {
553 KSPIN_CINSTANCES * Instances;
554 KSP_PIN * Pin = (KSP_PIN*)Request;
555
556 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
557 {
558 /* no filter / pin descriptor */
559 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
560 return STATUS_NOT_IMPLEMENTED;
561 }
562
563 /* ignore custom structs for now */
564 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
565 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
566
567 Instances = (KSPIN_CINSTANCES*)Data;
568 /* max instance count */
569 Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
570 /* current instance count */
571 Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
572
573 IoStatus->Information = sizeof(KSPIN_CINSTANCES);
574 IoStatus->Status = STATUS_SUCCESS;
575 return STATUS_SUCCESS;
576 }
577
578 NTSTATUS
579 KspHandleNecessaryPropertyInstances(
580 IN PIO_STATUS_BLOCK IoStatus,
581 IN PKSIDENTIFIER Request,
582 IN OUT PVOID Data,
583 IN IKsFilterImpl * This)
584 {
585 PULONG Result;
586 KSP_PIN * Pin = (KSP_PIN*)Request;
587
588 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
589 {
590 /* no filter / pin descriptor */
591 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
592 return STATUS_NOT_IMPLEMENTED;
593 }
594
595 /* ignore custom structs for now */
596 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
597 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
598
599 Result = (PULONG)Data;
600 *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
601
602 IoStatus->Information = sizeof(ULONG);
603 IoStatus->Status = STATUS_SUCCESS;
604 return STATUS_SUCCESS;
605 }
606
607 NTSTATUS
608 KspHandleDataIntersection(
609 IN PIRP Irp,
610 IN PIO_STATUS_BLOCK IoStatus,
611 IN PKSIDENTIFIER Request,
612 IN OUT PVOID Data,
613 IN ULONG DataLength,
614 IN IKsFilterImpl * This)
615 {
616 PKSMULTIPLE_ITEM MultipleItem;
617 PKSDATARANGE DataRange;
618 NTSTATUS Status = STATUS_NO_MATCH;
619 ULONG Index, Length;
620 PIO_STACK_LOCATION IoStack;
621 KSP_PIN * Pin = (KSP_PIN*)Request;
622
623 /* get stack location */
624 IoStack = IoGetCurrentIrpStackLocation(Irp);
625
626 /* sanity check */
627 ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
628
629 /* Access parameters */
630 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
631 DataRange = (PKSDATARANGE)(MultipleItem + 1);
632
633 /* FIXME make sure its 64 bit aligned */
634 ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
635
636 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
637 {
638 /* no filter / pin descriptor */
639 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
640 return STATUS_NOT_IMPLEMENTED;
641 }
642
643 /* ignore custom structs for now */
644 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
645 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
646
647 if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
648 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
649 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
650 {
651 /* no driver supported intersect handler / no provided data ranges */
652 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
653 return STATUS_NOT_IMPLEMENTED;
654 }
655
656 for(Index = 0; Index < MultipleItem->Count; Index++)
657 {
658 UNICODE_STRING MajorFormat, SubFormat, Specifier;
659 /* convert the guid to string */
660 RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat);
661 RtlStringFromGUID(&DataRange->SubFormat, &SubFormat);
662 RtlStringFromGUID(&DataRange->Specifier, &Specifier);
663
664 DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer,
665 DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength);
666
667 /* FIXME implement KsPinDataIntersectionEx */
668 /* Call miniport's properitary handler */
669 Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter,
670 Irp,
671 Pin,
672 DataRange,
673 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */
674 DataLength,
675 Data,
676 &Length);
677 DPRINT("KspHandleDataIntersection Status %lx\n", Status);
678
679 if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
680 {
681 ASSERT(Length);
682 IoStatus->Information = Length;
683 break;
684 }
685
686 DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
687 /* FIXME make sure its 64 bit aligned */
688 ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
689 }
690 IoStatus->Status = Status;
691 return Status;
692 }
693
694 NTSTATUS
695 NTAPI
696 FilterTopologyPropertyHandler(
697 IN PIRP Irp,
698 IN PKSIDENTIFIER Request,
699 IN OUT PVOID Data)
700 {
701 IKsFilterImpl * This;
702
703 /* get filter implementation */
704 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
705
706 /* sanity check */
707 ASSERT(This);
708
709 return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology);
710
711 }
712
713
714 NTSTATUS
715 NTAPI
716 FilterPinPropertyHandler(
717 IN PIRP Irp,
718 IN PKSIDENTIFIER Request,
719 IN OUT PVOID Data)
720 {
721 PIO_STACK_LOCATION IoStack;
722 IKsFilterImpl * This;
723 NTSTATUS Status = STATUS_UNSUCCESSFUL;
724
725 /* get filter implementation */
726 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
727
728 /* sanity check */
729 ASSERT(This);
730
731 /* get current stack location */
732 IoStack = IoGetCurrentIrpStackLocation(Irp);
733
734 switch(Request->Id)
735 {
736 case KSPROPERTY_PIN_CTYPES:
737 case KSPROPERTY_PIN_DATAFLOW:
738 case KSPROPERTY_PIN_DATARANGES:
739 case KSPROPERTY_PIN_INTERFACES:
740 case KSPROPERTY_PIN_MEDIUMS:
741 case KSPROPERTY_PIN_COMMUNICATION:
742 case KSPROPERTY_PIN_CATEGORY:
743 case KSPROPERTY_PIN_NAME:
744 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
745 Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize);
746 break;
747 case KSPROPERTY_PIN_GLOBALCINSTANCES:
748 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
749 break;
750 case KSPROPERTY_PIN_CINSTANCES:
751 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
752 break;
753 case KSPROPERTY_PIN_NECESSARYINSTANCES:
754 Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
755 break;
756
757 case KSPROPERTY_PIN_DATAINTERSECTION:
758 Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
759 break;
760 default:
761 UNIMPLEMENTED
762 Status = STATUS_NOT_FOUND;
763 }
764 //DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
765
766
767 return Status;
768 }
769
770 NTSTATUS
771 NTAPI
772 IKsFilter_DispatchDeviceIoControl(
773 IN PDEVICE_OBJECT DeviceObject,
774 IN PIRP Irp)
775 {
776 PIO_STACK_LOCATION IoStack;
777 IKsFilter * Filter;
778 IKsFilterImpl * This;
779 NTSTATUS Status;
780 PKSFILTER FilterInstance;
781 UNICODE_STRING GuidString;
782 PKSPROPERTY Property;
783 ULONG SetCount = 0;
784
785 /* obtain filter from object header */
786 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
787 if (!NT_SUCCESS(Status))
788 return Status;
789
790 /* get our real implementation */
791 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
792
793 /* current irp stack */
794 IoStack = IoGetCurrentIrpStackLocation(Irp);
795
796 /* get property from input buffer */
797 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
798
799 /* get filter instance */
800 FilterInstance = Filter->lpVtbl->GetStruct(Filter);
801
802 /* sanity check */
803 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
804 ASSERT(FilterInstance);
805 ASSERT(FilterInstance->Descriptor);
806 ASSERT(FilterInstance->Descriptor->AutomationTable);
807
808 /* acquire control mutex */
809 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
810
811 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
812 {
813 const KSMETHOD_SET *MethodSet = NULL;
814 ULONG MethodItemSize = 0;
815
816 /* check if the driver supports method sets */
817 if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
818 {
819 SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
820 MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
821 MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
822 }
823
824 /* call method set handler */
825 Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
826 }
827 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
828 {
829 const KSPROPERTY_SET *PropertySet = NULL;
830 ULONG PropertyItemSize = 0;
831
832 /* check if the driver supports method sets */
833 if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
834 {
835 SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
836 PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
837 PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
838 }
839
840 /* needed for our property handlers */
841 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
842
843 /* call property handler */
844 Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
845 }
846 else
847 {
848 /* sanity check */
849 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
850 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
851
852 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
853 {
854 /* call enable event handlers */
855 Status = KspEnableEvent(Irp,
856 FilterInstance->Descriptor->AutomationTable->EventSetsCount,
857 (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
858 &This->Header.EventList,
859 KSEVENTS_SPINLOCK,
860 (PVOID)&This->Header.EventListLock,
861 NULL,
862 FilterInstance->Descriptor->AutomationTable->EventItemSize);
863 }
864 else
865 {
866 /* disable event handler */
867 Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
868 }
869 }
870
871 RtlStringFromGUID(&Property->Set, &GuidString);
872 DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
873 RtlFreeUnicodeString(&GuidString);
874
875 /* release filter */
876 Filter->lpVtbl->Release(Filter);
877
878 /* release control mutex */
879 KeReleaseMutex(This->Header.ControlMutex, FALSE);
880
881 if (Status != STATUS_PENDING)
882 {
883 Irp->IoStatus.Status = Status;
884 IoCompleteRequest(Irp, IO_NO_INCREMENT);
885 }
886
887 /* done */
888 return Status;
889 }
890
891 static KSDISPATCH_TABLE DispatchTable =
892 {
893 IKsFilter_DispatchDeviceIoControl,
894 KsDispatchInvalidDeviceRequest,
895 KsDispatchInvalidDeviceRequest,
896 KsDispatchInvalidDeviceRequest,
897 IKsFilter_DispatchClose,
898 KsDispatchQuerySecurity,
899 KsDispatchSetSecurity,
900 KsDispatchFastIoDeviceControlFailure,
901 KsDispatchFastReadFailure,
902 KsDispatchFastReadFailure,
903 };
904
905
906 NTSTATUS
907 IKsFilter_CreateDescriptors(
908 IKsFilterImpl * This,
909 KSFILTER_DESCRIPTOR* FilterDescriptor)
910 {
911 ULONG Index = 0;
912 NTSTATUS Status;
913
914 /* initialize pin descriptors */
915 This->FirstPin = NULL;
916 This->PinInstanceCount = NULL;
917 This->ProcessPinIndex = NULL;
918
919 /* initialize topology descriptor */
920 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
921 This->Topology.Categories = FilterDescriptor->Categories;
922 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
923 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
924 This->Topology.TopologyConnections = FilterDescriptor->Connections;
925
926 /* are there any templates */
927 if (FilterDescriptor->PinDescriptorsCount)
928 {
929 /* sanity check */
930 ASSERT(FilterDescriptor->PinDescriptors);
931
932 /* FIXME handle variable sized pin descriptors */
933 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
934
935 /* store pin descriptors ex */
936 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
937 FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
938
939 if (!NT_SUCCESS(Status))
940 {
941 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
942 return Status;
943 }
944
945 /* store pin instance count */
946 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
947 sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
948
949 if (!NT_SUCCESS(Status))
950 {
951 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
952 return Status;
953 }
954
955 /* store instantiated pin arrays */
956 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
957 sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
958
959 if (!NT_SUCCESS(Status))
960 {
961 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
962 return Status;
963 }
964
965 /* add new pin factory */
966 RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
967
968 /* allocate process pin index */
969 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
970 sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
971
972 if (!NT_SUCCESS(Status))
973 {
974 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
975 return Status;
976 }
977
978 }
979
980
981 if (FilterDescriptor->ConnectionsCount)
982 {
983 /* modify connections array */
984 Status = _KsEdit(This->Filter.Bag,
985 (PVOID*)&This->Filter.Descriptor->Connections,
986 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
987 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
988 0);
989
990 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
991 This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
992 }
993
994 if (FilterDescriptor->NodeDescriptorsCount)
995 {
996 /* sanity check */
997 ASSERT(FilterDescriptor->NodeDescriptors);
998
999 /* FIXME handle variable sized node descriptors */
1000 ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
1001
1002 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1003 /* allocate topology node types array */
1004 if (!This->Topology.TopologyNodes)
1005 {
1006 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1007 return STATUS_INSUFFICIENT_RESOURCES;
1008 }
1009
1010 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1011 /* allocate topology names array */
1012 if (!This->Topology.TopologyNodesNames)
1013 {
1014 FreeItem((PVOID)This->Topology.TopologyNodes);
1015 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1016 return STATUS_INSUFFICIENT_RESOURCES;
1017 }
1018
1019 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1020 for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
1021 {
1022 DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
1023
1024 /* copy topology type */
1025 if (FilterDescriptor->NodeDescriptors[Index].Type)
1026 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
1027
1028 /* copy topology name */
1029 if (FilterDescriptor->NodeDescriptors[Index].Name)
1030 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
1031 }
1032 }
1033 /* done! */
1034 return STATUS_SUCCESS;
1035 }
1036
1037 NTSTATUS
1038 IKsFilter_CopyFilterDescriptor(
1039 IKsFilterImpl * This,
1040 const KSFILTER_DESCRIPTOR* FilterDescriptor)
1041 {
1042 NTSTATUS Status;
1043 KSAUTOMATION_TABLE AutomationTable;
1044
1045 This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
1046 if (!This->Filter.Descriptor)
1047 return STATUS_INSUFFICIENT_RESOURCES;
1048
1049 Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
1050 if (!NT_SUCCESS(Status))
1051 {
1052 FreeItem((PVOID)This->Filter.Descriptor);
1053 This->Filter.Descriptor = NULL;
1054 return STATUS_INSUFFICIENT_RESOURCES;
1055 }
1056
1057 /* copy filter descriptor fields */
1058 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
1059
1060 /* zero automation table */
1061 RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
1062
1063 /* setup filter property sets */
1064 AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
1065 AutomationTable.PropertySetsCount = 2;
1066 AutomationTable.PropertySets = FilterPropertySet;
1067
1068 /* merge filter automation table */
1069 Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
1070
1071 return Status;
1072 }
1073
1074
1075 VOID
1076 IKsFilter_AddPin(
1077 PKSFILTER Filter,
1078 PKSPIN Pin)
1079 {
1080 PKSPIN NextPin, CurPin;
1081 PKSBASIC_HEADER BasicHeader;
1082 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1083
1084 /* sanity check */
1085 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1086
1087 if (This->FirstPin[Pin->Id] == NULL)
1088 {
1089 /* welcome first pin */
1090 This->FirstPin[Pin->Id] = Pin;
1091 This->PinInstanceCount[Pin->Id]++;
1092 return;
1093 }
1094
1095 /* get first pin */
1096 CurPin = This->FirstPin[Pin->Id];
1097
1098 do
1099 {
1100 /* get next instantiated pin */
1101 NextPin = KsPinGetNextSiblingPin(CurPin);
1102 if (!NextPin)
1103 break;
1104
1105 NextPin = CurPin;
1106
1107 }while(NextPin != NULL);
1108
1109 /* get basic header */
1110 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
1111
1112 /* store pin */
1113 BasicHeader->Next.Pin = Pin;
1114 }
1115
1116 VOID
1117 IKsFilter_RemovePin(
1118 PKSFILTER Filter,
1119 PKSPIN Pin)
1120 {
1121 PKSPIN NextPin, CurPin, LastPin;
1122 PKSBASIC_HEADER BasicHeader;
1123 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1124
1125 /* sanity check */
1126 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1127
1128 /* get first pin */
1129 CurPin = This->FirstPin[Pin->Id];
1130
1131 LastPin = NULL;
1132 do
1133 {
1134 /* get next instantiated pin */
1135 NextPin = KsPinGetNextSiblingPin(CurPin);
1136
1137 if (CurPin == Pin)
1138 {
1139 if (LastPin)
1140 {
1141 /* get basic header of last pin */
1142 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
1143
1144 BasicHeader->Next.Pin = NextPin;
1145 }
1146 else
1147 {
1148 /* erase last pin */
1149 This->FirstPin[Pin->Id] = NextPin;
1150 }
1151 /* decrement pin instance count */
1152 This->PinInstanceCount[Pin->Id]--;
1153 return;
1154 }
1155
1156 if (!NextPin)
1157 break;
1158
1159 LastPin = CurPin;
1160 NextPin = CurPin;
1161
1162 }while(NextPin != NULL);
1163
1164 /* pin not found */
1165 ASSERT(0);
1166 }
1167
1168
1169 NTSTATUS
1170 NTAPI
1171 IKsFilter_DispatchCreatePin(
1172 IN PDEVICE_OBJECT DeviceObject,
1173 IN PIRP Irp)
1174 {
1175 IKsFilterImpl * This;
1176 PKSOBJECT_CREATE_ITEM CreateItem;
1177 PKSPIN_CONNECT Connect;
1178 NTSTATUS Status;
1179
1180 DPRINT("IKsFilter_DispatchCreatePin\n");
1181
1182 /* get the create item */
1183 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1184
1185 /* get the filter object */
1186 This = (IKsFilterImpl*)CreateItem->Context;
1187
1188 /* sanity check */
1189 ASSERT(This->Header.Type == KsObjectTypeFilter);
1190
1191 /* acquire control mutex */
1192 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1193
1194 /* now validate the connect request */
1195 Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
1196
1197 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
1198
1199 if (NT_SUCCESS(Status))
1200 {
1201 /* sanity check */
1202 ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
1203
1204 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1205 This->PinInstanceCount[Connect->PinId],
1206 This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
1207
1208 if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
1209 {
1210 /* create the pin */
1211 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
1212
1213 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status);
1214 }
1215 else
1216 {
1217 /* maximum instance count reached, bye-bye */
1218 Status = STATUS_UNSUCCESSFUL;
1219 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1220 }
1221 }
1222
1223 /* release control mutex */
1224 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1225
1226 if (Status != STATUS_PENDING)
1227 {
1228 /* complete request */
1229 Irp->IoStatus.Status = Status;
1230 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1231 }
1232
1233 /* done */
1234 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1235 return Status;
1236 }
1237
1238 NTSTATUS
1239 NTAPI
1240 IKsFilter_DispatchCreateNode(
1241 IN PDEVICE_OBJECT DeviceObject,
1242 IN PIRP Irp)
1243 {
1244 UNIMPLEMENTED
1245 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1246 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1247 return STATUS_UNSUCCESSFUL;
1248 }
1249
1250
1251 VOID
1252 IKsFilter_AttachFilterToFilterFactory(
1253 IKsFilterImpl * This,
1254 PKSFILTERFACTORY FilterFactory)
1255 {
1256 PKSBASIC_HEADER BasicHeader;
1257 PKSFILTER Filter;
1258
1259
1260 /* get filter factory basic header */
1261 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1262
1263 /* sanity check */
1264 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1265
1266 if (BasicHeader->FirstChild.FilterFactory == NULL)
1267 {
1268 /* welcome first instantiated filter */
1269 BasicHeader->FirstChild.Filter = &This->Filter;
1270 return;
1271 }
1272
1273 /* set to first entry */
1274 Filter = BasicHeader->FirstChild.Filter;
1275
1276 do
1277 {
1278 /* get basic header */
1279 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1280 /* sanity check */
1281 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1282
1283 if (BasicHeader->Next.Filter)
1284 {
1285 /* iterate to next filter factory */
1286 Filter = BasicHeader->Next.Filter;
1287 }
1288 else
1289 {
1290 /* found last entry */
1291 break;
1292 }
1293 }while(TRUE);
1294
1295 /* attach filter factory */
1296 BasicHeader->Next.Filter = &This->Filter;
1297 }
1298
1299 VOID
1300 IKsFilter_RemoveFilterFromFilterFactory(
1301 IKsFilterImpl * This,
1302 PKSFILTERFACTORY FilterFactory)
1303 {
1304 PKSBASIC_HEADER BasicHeader;
1305 PKSFILTER Filter, LastFilter;
1306
1307 /* get filter factory basic header */
1308 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1309
1310 /* sanity check */
1311 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1312 ASSERT(BasicHeader->FirstChild.Filter != NULL);
1313
1314
1315 /* set to first entry */
1316 Filter = BasicHeader->FirstChild.Filter;
1317 LastFilter = NULL;
1318
1319 do
1320 {
1321 if (Filter == &This->Filter)
1322 {
1323 if (LastFilter)
1324 {
1325 /* get basic header */
1326 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
1327 /* remove filter instance */
1328 BasicHeader->Next.Filter = This->Header.Next.Filter;
1329 break;
1330 }
1331 else
1332 {
1333 /* remove filter instance */
1334 BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
1335 break;
1336 }
1337 }
1338
1339 /* get basic header */
1340 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1341 /* sanity check */
1342 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1343
1344 LastFilter = Filter;
1345 if (BasicHeader->Next.Filter)
1346 {
1347 /* iterate to next filter factory */
1348 Filter = BasicHeader->Next.Filter;
1349 }
1350 else
1351 {
1352 /* filter is not in list */
1353 ASSERT(0);
1354 break;
1355 }
1356 }while(TRUE);
1357 }
1358
1359 NTSTATUS
1360 NTAPI
1361 KspCreateFilter(
1362 IN PDEVICE_OBJECT DeviceObject,
1363 IN PIRP Irp,
1364 IN IKsFilterFactory *iface)
1365 {
1366 IKsFilterImpl * This;
1367 IKsDevice *KsDevice;
1368 PKSFILTERFACTORY Factory;
1369 PIO_STACK_LOCATION IoStack;
1370 PDEVICE_EXTENSION DeviceExtension;
1371 NTSTATUS Status;
1372 PKSOBJECT_CREATE_ITEM CreateItem;
1373
1374 /* get device extension */
1375 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1376
1377 /* get the filter factory */
1378 Factory = iface->lpVtbl->GetStruct(iface);
1379
1380 if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
1381 {
1382 /* Sorry it just will not work */
1383 return STATUS_UNSUCCESSFUL;
1384 }
1385
1386 /* allocate filter instance */
1387 This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1388 if (!This)
1389 {
1390 DPRINT("KspCreateFilter OutOfMemory\n");
1391 return STATUS_INSUFFICIENT_RESOURCES;
1392 }
1393
1394 /* initialize object bag */
1395 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1396 if (!This->Filter.Bag)
1397 {
1398 /* no memory */
1399 FreeItem(This);
1400 DPRINT("KspCreateFilter OutOfMemory\n");
1401 return STATUS_INSUFFICIENT_RESOURCES;
1402 }
1403 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
1404 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1405
1406 /* copy filter descriptor */
1407 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1408 if (!NT_SUCCESS(Status))
1409 {
1410 /* not enough memory */
1411 FreeItem(This->Filter.Bag);
1412 FreeItem(This);
1413 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1414 return STATUS_INSUFFICIENT_RESOURCES;
1415 }
1416
1417 /* get current irp stack */
1418 IoStack = IoGetCurrentIrpStackLocation(Irp);
1419
1420 /* allocate create items */
1421 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1422 if (!CreateItem)
1423 {
1424 /* no memory */
1425 FreeItem(This->Filter.Bag);
1426 FreeItem(This);
1427 DPRINT("KspCreateFilter OutOfMemory\n");
1428 return STATUS_INSUFFICIENT_RESOURCES;
1429 }
1430
1431 DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags);
1432
1433 /* initialize pin create item */
1434 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1435 CreateItem[0].Context = (PVOID)This;
1436 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1437 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1438 /* initialize node create item */
1439 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1440 CreateItem[1].Context = (PVOID)This;
1441 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1442 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1443
1444
1445 /* initialize filter instance */
1446 This->ref = 1;
1447 This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
1448 This->lpVtblKsControl = &vt_IKsControl;
1449
1450 This->Factory = Factory;
1451 This->FilterFactory = iface;
1452 This->FileObject = IoStack->FileObject;
1453 KeInitializeMutex(&This->ProcessingMutex, 0);
1454 /* initialize basic header */
1455 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1456 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1457 This->Header.Type = KsObjectTypeFilter;
1458 This->Header.ControlMutex = &This->ControlMutex;
1459 KeInitializeMutex(This->Header.ControlMutex, 0);
1460 InitializeListHead(&This->Header.EventList);
1461 KeInitializeSpinLock(&This->Header.EventListLock);
1462
1463 /* allocate the stream descriptors */
1464 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1465 if (!NT_SUCCESS(Status))
1466 {
1467 /* what can go wrong, goes wrong */
1468 FreeItem(This);
1469 FreeItem(CreateItem);
1470 DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1471 return Status;
1472 }
1473
1474 /* does the filter have a filter dispatch */
1475 if (Factory->FilterDescriptor->Dispatch)
1476 {
1477 /* does it have a create routine */
1478 if (Factory->FilterDescriptor->Dispatch->Create)
1479 {
1480 /* now let driver initialize the filter instance */
1481
1482 ASSERT(This->Header.KsDevice);
1483 ASSERT(This->Header.KsDevice->Started);
1484 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1485
1486 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1487 {
1488 /* driver failed to initialize */
1489 DPRINT1("Driver: Status %x\n", Status);
1490
1491 /* free filter instance */
1492 FreeItem(This);
1493 FreeItem(CreateItem);
1494 return Status;
1495 }
1496 }
1497 }
1498
1499 /* now allocate the object header */
1500 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1501 if (!NT_SUCCESS(Status))
1502 {
1503 /* failed to allocate object header */
1504 DPRINT1("Failed to allocate object header %x\n", Status);
1505
1506 return Status;
1507 }
1508
1509 /* initialize object header extra fields */
1510 This->ObjectHeader->Type = KsObjectTypeFilter;
1511 This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
1512 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1513
1514 /* attach filter to filter factory */
1515 IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1516
1517 /* completed initialization */
1518 DPRINT("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
1519 return Status;
1520 }
1521
1522 /*
1523 @implemented
1524 */
1525 KSDDKAPI
1526 VOID
1527 NTAPI
1528 KsFilterAcquireProcessingMutex(
1529 IN PKSFILTER Filter)
1530 {
1531 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1532
1533 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1534 }
1535
1536 /*
1537 @implemented
1538 */
1539 KSDDKAPI
1540 VOID
1541 NTAPI
1542 KsFilterReleaseProcessingMutex(
1543 IN PKSFILTER Filter)
1544 {
1545 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1546
1547 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1548 }
1549
1550
1551 /*
1552 @implemented
1553 */
1554 KSDDKAPI
1555 NTSTATUS
1556 NTAPI
1557 KsFilterAddTopologyConnections (
1558 IN PKSFILTER Filter,
1559 IN ULONG NewConnectionsCount,
1560 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1561 {
1562 ULONG Count;
1563 NTSTATUS Status;
1564 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1565
1566 DPRINT("KsFilterAddTopologyConnections\n");
1567
1568 ASSERT(This->Filter.Descriptor);
1569 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1570
1571
1572 /* modify connections array */
1573 Status = _KsEdit(This->Filter.Bag,
1574 (PVOID*)&This->Filter.Descriptor->Connections,
1575 Count * sizeof(KSTOPOLOGY_CONNECTION),
1576 This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1577 0);
1578
1579 if (!NT_SUCCESS(Status))
1580 {
1581 /* failed */
1582 DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
1583 return Status;
1584 }
1585
1586 /* FIXME verify connections */
1587
1588 /* copy new connections */
1589 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
1590 NewTopologyConnections,
1591 NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
1592
1593 /* update topology */
1594 This->Topology.TopologyConnectionsCount += NewConnectionsCount;
1595 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
1596 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1597
1598 return Status;
1599 }
1600
1601 /*
1602 @unimplemented
1603 */
1604 KSDDKAPI
1605 VOID
1606 NTAPI
1607 KsFilterAttemptProcessing(
1608 IN PKSFILTER Filter,
1609 IN BOOLEAN Asynchronous)
1610 {
1611 UNIMPLEMENTED
1612 }
1613
1614 /*
1615 @unimplemented
1616 */
1617 KSDDKAPI
1618 NTSTATUS
1619 NTAPI
1620 KsFilterCreateNode (
1621 IN PKSFILTER Filter,
1622 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1623 OUT PULONG NodeID)
1624 {
1625 UNIMPLEMENTED
1626 return STATUS_NOT_IMPLEMENTED;
1627 }
1628
1629 /*
1630 @implemented
1631 */
1632 KSDDKAPI
1633 NTSTATUS
1634 NTAPI
1635 KsFilterCreatePinFactory (
1636 IN PKSFILTER Filter,
1637 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1638 OUT PULONG PinID)
1639 {
1640 ULONG Count;
1641 NTSTATUS Status;
1642 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1643
1644 DPRINT("KsFilterCreatePinFactory\n");
1645
1646 /* calculate new count */
1647 Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
1648
1649 /* sanity check */
1650 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1651
1652 /* modify pin descriptors ex array */
1653 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0);
1654 if (!NT_SUCCESS(Status))
1655 {
1656 /* failed */
1657 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1658 return Status;
1659 }
1660
1661 /* modify pin instance count array */
1662 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1663 if (!NT_SUCCESS(Status))
1664 {
1665 /* failed */
1666 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1667 return Status;
1668 }
1669
1670 /* modify first pin array */
1671 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1672 if (!NT_SUCCESS(Status))
1673 {
1674 /* failed */
1675 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1676 return Status;
1677 }
1678
1679 /* add new pin factory */
1680 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
1681
1682 /* allocate process pin index */
1683 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
1684 sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1685
1686 if (!NT_SUCCESS(Status))
1687 {
1688 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
1689 return Status;
1690 }
1691
1692 /* store new pin id */
1693 *PinID = This->Filter.Descriptor->PinDescriptorsCount;
1694
1695 /* increment pin descriptor count */
1696 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
1697
1698
1699 DPRINT("KsFilterCreatePinFactory done\n");
1700 return STATUS_SUCCESS;
1701
1702 }
1703
1704 /*
1705 @unimplemented
1706 */
1707 KSDDKAPI
1708 PKSGATE
1709 NTAPI
1710 KsFilterGetAndGate(
1711 IN PKSFILTER Filter)
1712 {
1713 UNIMPLEMENTED
1714 return NULL;
1715 }
1716
1717 /*
1718 @implemented
1719 */
1720 KSDDKAPI
1721 ULONG
1722 NTAPI
1723 KsFilterGetChildPinCount(
1724 IN PKSFILTER Filter,
1725 IN ULONG PinId)
1726 {
1727 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1728
1729 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
1730 {
1731 /* index is out of bounds */
1732 return 0;
1733 }
1734 /* return pin instance count */
1735 return This->PinInstanceCount[PinId];
1736 }
1737
1738 /*
1739 @implemented
1740 */
1741 KSDDKAPI
1742 PKSPIN
1743 NTAPI
1744 KsFilterGetFirstChildPin(
1745 IN PKSFILTER Filter,
1746 IN ULONG PinId)
1747 {
1748 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1749
1750 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
1751 {
1752 /* index is out of bounds */
1753 return NULL;
1754 }
1755
1756 /* return first pin index */
1757 return This->FirstPin[PinId];
1758 }
1759
1760 /*
1761 @implemented
1762 */
1763 KSDDKAPI
1764 VOID
1765 NTAPI
1766 KsFilterRegisterPowerCallbacks(
1767 IN PKSFILTER Filter,
1768 IN PFNKSFILTERPOWER Sleep OPTIONAL,
1769 IN PFNKSFILTERPOWER Wake OPTIONAL)
1770 {
1771 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1772
1773 This->Sleep = Sleep;
1774 This->Wake = Wake;
1775 }
1776
1777 /*
1778 @implemented
1779 */
1780 KSDDKAPI
1781 PKSFILTER
1782 NTAPI
1783 KsGetFilterFromIrp(
1784 IN PIRP Irp)
1785 {
1786 PIO_STACK_LOCATION IoStack;
1787 PKSIOBJECT_HEADER ObjectHeader;
1788
1789 DPRINT("KsGetFilterFromIrp\n");
1790
1791 /* get current irp stack location */
1792 IoStack = IoGetCurrentIrpStackLocation(Irp);
1793
1794 /* sanity check */
1795 ASSERT(IoStack->FileObject);
1796
1797 /* get object header */
1798 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1799
1800 if (ObjectHeader->Type == KsObjectTypeFilter)
1801 {
1802 /* irp is targeted at the filter */
1803 return (PKSFILTER)ObjectHeader->ObjectType;
1804 }
1805 else if (ObjectHeader->Type == KsObjectTypePin)
1806 {
1807 /* irp is for a pin */
1808 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
1809 }
1810 else
1811 {
1812 /* irp is unappropiate to retrieve a filter */
1813 return NULL;
1814 }
1815 }