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