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