Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[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(PVOID),
516 This->Filter.Descriptor->PinDescriptorsCount * sizeof(PVOID),
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(PVOID));
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 = (PKSDATARANGE)((PUCHAR)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->Filter.Descriptor->PinDescriptorsCount, 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 // FIXME: handle variable sized property items
1033 ASSERT(PropertyItemSize == sizeof(KSPROPERTY_ITEM));
1034 PropertyItemSize = 0;
1035 }
1036
1037 /* needed for our property handlers */
1038 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
1039
1040 /* call property handler */
1041 Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
1042 }
1043 else
1044 {
1045 /* sanity check */
1046 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
1047 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
1048
1049 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
1050 {
1051 /* call enable event handlers */
1052 Status = KspEnableEvent(Irp,
1053 FilterInstance->Descriptor->AutomationTable->EventSetsCount,
1054 (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
1055 &This->Header.EventList,
1056 KSEVENTS_SPINLOCK,
1057 (PVOID)&This->Header.EventListLock,
1058 NULL,
1059 FilterInstance->Descriptor->AutomationTable->EventItemSize);
1060 }
1061 else
1062 {
1063 /* disable event handler */
1064 Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
1065 }
1066 }
1067
1068 RtlStringFromGUID(&Property->Set, &GuidString);
1069 DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance->Descriptor->PinDescriptorsCount);
1070 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);
1071 RtlFreeUnicodeString(&GuidString);
1072
1073 /* release filter */
1074 Filter->lpVtbl->Release(Filter);
1075
1076 /* release control mutex */
1077 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1078
1079 if (Status != STATUS_PENDING)
1080 {
1081 Irp->IoStatus.Status = Status;
1082 CompleteRequest(Irp, IO_NO_INCREMENT);
1083 }
1084
1085 /* done */
1086 return Status;
1087 }
1088
1089 static KSDISPATCH_TABLE DispatchTable =
1090 {
1091 IKsFilter_DispatchDeviceIoControl,
1092 KsDispatchInvalidDeviceRequest,
1093 KsDispatchInvalidDeviceRequest,
1094 KsDispatchInvalidDeviceRequest,
1095 IKsFilter_DispatchClose,
1096 KsDispatchQuerySecurity,
1097 KsDispatchSetSecurity,
1098 KsDispatchFastIoDeviceControlFailure,
1099 KsDispatchFastReadFailure,
1100 KsDispatchFastReadFailure,
1101 };
1102
1103
1104 NTSTATUS
1105 IKsFilter_CreateDescriptors(
1106 IKsFilterImpl * This,
1107 KSFILTER_DESCRIPTOR* FilterDescriptor)
1108 {
1109 ULONG Index = 0;
1110 NTSTATUS Status;
1111 PKSNODE_DESCRIPTOR NodeDescriptor;
1112
1113 /* initialize pin descriptors */
1114 This->FirstPin = NULL;
1115 This->PinInstanceCount = NULL;
1116 This->ProcessPinIndex = NULL;
1117
1118 /* initialize topology descriptor */
1119 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
1120 This->Topology.Categories = FilterDescriptor->Categories;
1121 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
1122 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
1123 This->Topology.TopologyConnections = FilterDescriptor->Connections;
1124
1125 /* are there any templates */
1126 if (FilterDescriptor->PinDescriptorsCount)
1127 {
1128 /* sanity check */
1129 ASSERT(FilterDescriptor->PinDescriptors);
1130
1131 /* FIXME handle variable sized pin descriptors */
1132 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1133
1134 /* store pin descriptors ex */
1135 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
1136 FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
1137
1138 if (!NT_SUCCESS(Status))
1139 {
1140 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1141 return Status;
1142 }
1143
1144 /* store pin instance count */
1145 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
1146 sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
1147
1148 if (!NT_SUCCESS(Status))
1149 {
1150 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1151 return Status;
1152 }
1153
1154 /* store instantiated pin arrays */
1155 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount,
1156 sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount, 0);
1157
1158 if (!NT_SUCCESS(Status))
1159 {
1160 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1161 return Status;
1162 }
1163
1164 /* add new pin factory */
1165 RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
1166
1167 /* allocate process pin index */
1168 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
1169 sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
1170
1171 if (!NT_SUCCESS(Status))
1172 {
1173 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1174 return Status;
1175 }
1176
1177 }
1178
1179
1180 if (FilterDescriptor->ConnectionsCount)
1181 {
1182 /* modify connections array */
1183 Status = _KsEdit(This->Filter.Bag,
1184 (PVOID*)&This->Filter.Descriptor->Connections,
1185 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1186 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1187 0);
1188
1189 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1190 This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
1191 }
1192
1193 if (FilterDescriptor->NodeDescriptorsCount)
1194 {
1195 /* sanity check */
1196 ASSERT(FilterDescriptor->NodeDescriptors);
1197
1198 /* sanity check */
1199 ASSERT(FilterDescriptor->NodeDescriptorSize >= sizeof(KSNODE_DESCRIPTOR));
1200
1201 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1202 /* allocate topology node types array */
1203 if (!This->Topology.TopologyNodes)
1204 {
1205 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1206 return STATUS_INSUFFICIENT_RESOURCES;
1207 }
1208
1209 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1210 /* allocate topology names array */
1211 if (!This->Topology.TopologyNodesNames)
1212 {
1213 FreeItem((PVOID)This->Topology.TopologyNodes);
1214 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1215 return STATUS_INSUFFICIENT_RESOURCES;
1216 }
1217
1218 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1219 NodeDescriptor = (PKSNODE_DESCRIPTOR)FilterDescriptor->NodeDescriptors;
1220 for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
1221 {
1222 DPRINT("Index %lu Type %p Name %p\n", Index, NodeDescriptor->Type, NodeDescriptor->Name);
1223
1224 /* copy topology type */
1225 if (NodeDescriptor->Type)
1226 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
1227
1228 /* copy topology name */
1229 if (NodeDescriptor->Name)
1230 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
1231
1232 // next node descriptor
1233 NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescriptor->NodeDescriptorSize);
1234 }
1235 }
1236 /* done! */
1237 return STATUS_SUCCESS;
1238 }
1239
1240 NTSTATUS
1241 IKsFilter_CopyFilterDescriptor(
1242 IKsFilterImpl * This,
1243 const KSFILTER_DESCRIPTOR* FilterDescriptor)
1244 {
1245 NTSTATUS Status;
1246 KSAUTOMATION_TABLE AutomationTable;
1247
1248 This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
1249 if (!This->Filter.Descriptor)
1250 return STATUS_INSUFFICIENT_RESOURCES;
1251
1252 Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
1253 if (!NT_SUCCESS(Status))
1254 {
1255 FreeItem((PVOID)This->Filter.Descriptor);
1256 This->Filter.Descriptor = NULL;
1257 return STATUS_INSUFFICIENT_RESOURCES;
1258 }
1259
1260 /* copy filter descriptor fields */
1261 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
1262
1263 /* zero automation table */
1264 RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
1265
1266 /* setup filter property sets */
1267 AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
1268 AutomationTable.PropertySetsCount = 2;
1269 AutomationTable.PropertySets = FilterPropertySet;
1270
1271 /* merge filter automation table */
1272 Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
1273
1274 return Status;
1275 }
1276
1277
1278 VOID
1279 IKsFilter_AddPin(
1280 PKSFILTER Filter,
1281 PKSPIN Pin)
1282 {
1283 PKSPIN NextPin, CurPin;
1284 PKSBASIC_HEADER BasicHeader;
1285 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1286
1287 /* sanity check */
1288 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1289
1290 if (This->FirstPin[Pin->Id] == NULL)
1291 {
1292 /* welcome first pin */
1293 This->FirstPin[Pin->Id] = Pin;
1294 This->PinInstanceCount[Pin->Id]++;
1295 return;
1296 }
1297
1298 /* get first pin */
1299 CurPin = This->FirstPin[Pin->Id];
1300
1301 do
1302 {
1303 /* get next instantiated pin */
1304 NextPin = KsPinGetNextSiblingPin(CurPin);
1305 if (!NextPin)
1306 break;
1307
1308 NextPin = CurPin;
1309
1310 }while(NextPin != NULL);
1311
1312 /* get basic header */
1313 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
1314
1315 /* store pin */
1316 BasicHeader->Next.Pin = Pin;
1317 }
1318
1319 VOID
1320 IKsFilter_RemovePin(
1321 PKSFILTER Filter,
1322 PKSPIN Pin)
1323 {
1324 PKSPIN NextPin, CurPin, LastPin;
1325 PKSBASIC_HEADER BasicHeader;
1326 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1327
1328 /* sanity check */
1329 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1330
1331 /* get first pin */
1332 CurPin = This->FirstPin[Pin->Id];
1333
1334 LastPin = NULL;
1335 do
1336 {
1337 /* get next instantiated pin */
1338 NextPin = KsPinGetNextSiblingPin(CurPin);
1339
1340 if (CurPin == Pin)
1341 {
1342 if (LastPin)
1343 {
1344 /* get basic header of last pin */
1345 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
1346
1347 BasicHeader->Next.Pin = NextPin;
1348 }
1349 else
1350 {
1351 /* erase last pin */
1352 This->FirstPin[Pin->Id] = NextPin;
1353 }
1354 /* decrement pin instance count */
1355 This->PinInstanceCount[Pin->Id]--;
1356 return;
1357 }
1358
1359 if (!NextPin)
1360 break;
1361
1362 LastPin = CurPin;
1363 NextPin = CurPin;
1364
1365 }while(NextPin != NULL);
1366
1367 /* pin not found */
1368 ASSERT(0);
1369 }
1370
1371
1372 NTSTATUS
1373 NTAPI
1374 IKsFilter_DispatchCreatePin(
1375 IN PDEVICE_OBJECT DeviceObject,
1376 IN PIRP Irp)
1377 {
1378 IKsFilterImpl * This;
1379 PKSOBJECT_CREATE_ITEM CreateItem;
1380 PKSPIN_CONNECT Connect;
1381 NTSTATUS Status;
1382
1383 DPRINT("IKsFilter_DispatchCreatePin\n");
1384
1385 /* get the create item */
1386 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1387
1388 /* get the filter object */
1389 This = (IKsFilterImpl*)CreateItem->Context;
1390
1391 /* sanity check */
1392 ASSERT(This->Header.Type == KsObjectTypeFilter);
1393
1394 /* acquire control mutex */
1395 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1396
1397 /* now validate the connect request */
1398 Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
1399
1400 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
1401
1402 if (NT_SUCCESS(Status))
1403 {
1404 /* sanity check */
1405 ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
1406
1407 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1408 This->PinInstanceCount[Connect->PinId],
1409 This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
1410
1411 if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
1412 {
1413 /* create the pin */
1414 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
1415
1416 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status);
1417 }
1418 else
1419 {
1420 /* maximum instance count reached, bye-bye */
1421 Status = STATUS_UNSUCCESSFUL;
1422 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1423 }
1424 }
1425
1426 /* release control mutex */
1427 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1428
1429 if (Status != STATUS_PENDING)
1430 {
1431 /* complete request */
1432 Irp->IoStatus.Status = Status;
1433 CompleteRequest(Irp, IO_NO_INCREMENT);
1434 }
1435
1436 /* done */
1437 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1438 return Status;
1439 }
1440
1441 NTSTATUS
1442 NTAPI
1443 IKsFilter_DispatchCreateNode(
1444 IN PDEVICE_OBJECT DeviceObject,
1445 IN PIRP Irp)
1446 {
1447 UNIMPLEMENTED
1448 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1449 CompleteRequest(Irp, IO_NO_INCREMENT);
1450 return STATUS_UNSUCCESSFUL;
1451 }
1452
1453
1454 VOID
1455 IKsFilter_AttachFilterToFilterFactory(
1456 IKsFilterImpl * This,
1457 PKSFILTERFACTORY FilterFactory)
1458 {
1459 PKSBASIC_HEADER BasicHeader;
1460 PKSFILTER Filter;
1461
1462
1463 /* get filter factory basic header */
1464 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1465
1466 /* sanity check */
1467 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1468
1469 if (BasicHeader->FirstChild.FilterFactory == NULL)
1470 {
1471 /* welcome first instantiated filter */
1472 BasicHeader->FirstChild.Filter = &This->Filter;
1473 return;
1474 }
1475
1476 /* set to first entry */
1477 Filter = BasicHeader->FirstChild.Filter;
1478
1479 do
1480 {
1481 /* get basic header */
1482 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1483 /* sanity check */
1484 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1485
1486 if (BasicHeader->Next.Filter)
1487 {
1488 /* iterate to next filter factory */
1489 Filter = BasicHeader->Next.Filter;
1490 }
1491 else
1492 {
1493 /* found last entry */
1494 break;
1495 }
1496 }while(TRUE);
1497
1498 /* attach filter factory */
1499 BasicHeader->Next.Filter = &This->Filter;
1500 }
1501
1502 VOID
1503 IKsFilter_RemoveFilterFromFilterFactory(
1504 IKsFilterImpl * This,
1505 PKSFILTERFACTORY FilterFactory)
1506 {
1507 PKSBASIC_HEADER BasicHeader;
1508 PKSFILTER Filter, LastFilter;
1509
1510 /* get filter factory basic header */
1511 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1512
1513 /* sanity check */
1514 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1515 ASSERT(BasicHeader->FirstChild.Filter != NULL);
1516
1517
1518 /* set to first entry */
1519 Filter = BasicHeader->FirstChild.Filter;
1520 LastFilter = NULL;
1521
1522 do
1523 {
1524 if (Filter == &This->Filter)
1525 {
1526 if (LastFilter)
1527 {
1528 /* get basic header */
1529 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
1530 /* remove filter instance */
1531 BasicHeader->Next.Filter = This->Header.Next.Filter;
1532 break;
1533 }
1534 else
1535 {
1536 /* remove filter instance */
1537 BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
1538 break;
1539 }
1540 }
1541
1542 /* get basic header */
1543 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1544 /* sanity check */
1545 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1546
1547 LastFilter = Filter;
1548 if (BasicHeader->Next.Filter)
1549 {
1550 /* iterate to next filter factory */
1551 Filter = BasicHeader->Next.Filter;
1552 }
1553 else
1554 {
1555 /* filter is not in list */
1556 ASSERT(0);
1557 break;
1558 }
1559 }while(TRUE);
1560 }
1561
1562 VOID
1563 NTAPI
1564 IKsFilter_FilterCentricWorker(
1565 IN PVOID Ctx)
1566 {
1567 IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
1568
1569 /* sanity check */
1570 ASSERT(Object);
1571
1572 /* perform work */
1573 Object->lpVtbl->ProcessingObjectWork(Object);
1574 }
1575
1576 NTSTATUS
1577 NTAPI
1578 KspCreateFilter(
1579 IN PDEVICE_OBJECT DeviceObject,
1580 IN PIRP Irp,
1581 IN IKsFilterFactory *iface)
1582 {
1583 IKsFilterImpl * This;
1584 IKsDevice *KsDevice;
1585 PKSFILTERFACTORY Factory;
1586 PIO_STACK_LOCATION IoStack;
1587 PDEVICE_EXTENSION DeviceExtension;
1588 NTSTATUS Status;
1589 PKSOBJECT_CREATE_ITEM CreateItem;
1590
1591 /* get device extension */
1592 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1593
1594 /* get the filter factory */
1595 Factory = iface->lpVtbl->GetStruct(iface);
1596
1597 if (!Factory || !Factory->FilterDescriptor)
1598 {
1599 /* Sorry it just will not work */
1600 return STATUS_UNSUCCESSFUL;
1601 }
1602
1603 if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
1604 {
1605 if (Irp->RequestorMode == UserMode)
1606 {
1607 /* filter not accessible from user mode */
1608 DPRINT1("Access denied\n");
1609 return STATUS_UNSUCCESSFUL;
1610 }
1611 }
1612
1613 /* allocate filter instance */
1614 This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1615 if (!This)
1616 {
1617 DPRINT1("KspCreateFilter OutOfMemory\n");
1618 return STATUS_INSUFFICIENT_RESOURCES;
1619 }
1620
1621 /* initialize object bag */
1622 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1623 if (!This->Filter.Bag)
1624 {
1625 /* no memory */
1626 FreeItem(This);
1627 DPRINT1("KspCreateFilter OutOfMemory\n");
1628 return STATUS_INSUFFICIENT_RESOURCES;
1629 }
1630 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
1631 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1632
1633 /* copy filter descriptor */
1634 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1635 if (!NT_SUCCESS(Status))
1636 {
1637 /* not enough memory */
1638 FreeItem(This->Filter.Bag);
1639 FreeItem(This);
1640 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1641 return STATUS_INSUFFICIENT_RESOURCES;
1642 }
1643
1644 /* get current irp stack */
1645 IoStack = IoGetCurrentIrpStackLocation(Irp);
1646
1647 /* allocate create items */
1648 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1649 if (!CreateItem)
1650 {
1651 /* no memory */
1652 FreeItem(This->Filter.Bag);
1653 FreeItem(This);
1654 DPRINT1("KspCreateFilter OutOfMemory\n");
1655 return STATUS_INSUFFICIENT_RESOURCES;
1656 }
1657
1658 /* initialize pin create item */
1659 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1660 CreateItem[0].Context = (PVOID)This;
1661 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1662 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1663 /* initialize node create item */
1664 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1665 CreateItem[1].Context = (PVOID)This;
1666 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1667 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1668
1669
1670 /* initialize filter instance */
1671 This->ref = 1;
1672 This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
1673 This->lpVtblKsControl = &vt_IKsControl;
1674 This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
1675
1676 This->Factory = Factory;
1677 This->FilterFactory = iface;
1678 This->FileObject = IoStack->FileObject;
1679 KeInitializeMutex(&This->ProcessingMutex, 0);
1680
1681 /* initialize basic header */
1682 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1683 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1684 This->Header.Type = KsObjectTypeFilter;
1685 This->Header.ControlMutex = &This->ControlMutex;
1686 KeInitializeMutex(This->Header.ControlMutex, 0);
1687 InitializeListHead(&This->Header.EventList);
1688 KeInitializeSpinLock(&This->Header.EventListLock);
1689
1690 /* initialize and gate */
1691 KsGateInitializeAnd(&This->Gate, NULL);
1692
1693 /* FIXME initialize and gate based on pin flags */
1694
1695 /* initialize work item */
1696 ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
1697
1698 /* allocate counted work item */
1699 Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
1700 if (!NT_SUCCESS(Status))
1701 {
1702 /* what can go wrong, goes wrong */
1703 DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
1704 FreeItem(This);
1705 FreeItem(CreateItem);
1706 return Status;
1707 }
1708
1709 /* allocate the stream descriptors */
1710 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1711 if (!NT_SUCCESS(Status))
1712 {
1713 /* what can go wrong, goes wrong */
1714 DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1715 KsUnregisterWorker(This->Worker);
1716 FreeItem(This);
1717 FreeItem(CreateItem);
1718 return Status;
1719 }
1720
1721
1722
1723 /* does the filter have a filter dispatch */
1724 if (Factory->FilterDescriptor->Dispatch)
1725 {
1726 /* does it have a create routine */
1727 if (Factory->FilterDescriptor->Dispatch->Create)
1728 {
1729 /* now let driver initialize the filter instance */
1730
1731 ASSERT(This->Header.KsDevice);
1732 ASSERT(This->Header.KsDevice->Started);
1733 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1734
1735 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1736 {
1737 /* driver failed to initialize */
1738 DPRINT1("Driver: Status %x\n", Status);
1739
1740 /* free filter instance */
1741 KsUnregisterWorker(This->Worker);
1742 FreeItem(This);
1743 FreeItem(CreateItem);
1744 return Status;
1745 }
1746 }
1747 }
1748
1749 /* now allocate the object header */
1750 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1751 if (!NT_SUCCESS(Status))
1752 {
1753 /* failed to allocate object header */
1754 DPRINT1("Failed to allocate object header %x\n", Status);
1755
1756 return Status;
1757 }
1758
1759 /* initialize object header extra fields */
1760 This->ObjectHeader->Type = KsObjectTypeFilter;
1761 This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
1762 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1763
1764 /* attach filter to filter factory */
1765 IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1766
1767 /* completed initialization */
1768 DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
1769 return Status;
1770 }
1771
1772 /*
1773 @implemented
1774 */
1775 KSDDKAPI
1776 VOID
1777 NTAPI
1778 KsFilterAcquireProcessingMutex(
1779 IN PKSFILTER Filter)
1780 {
1781 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1782
1783 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1784 }
1785
1786 /*
1787 @implemented
1788 */
1789 KSDDKAPI
1790 VOID
1791 NTAPI
1792 KsFilterReleaseProcessingMutex(
1793 IN PKSFILTER Filter)
1794 {
1795 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1796
1797 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1798 }
1799
1800
1801 /*
1802 @implemented
1803 */
1804 KSDDKAPI
1805 NTSTATUS
1806 NTAPI
1807 KsFilterAddTopologyConnections (
1808 IN PKSFILTER Filter,
1809 IN ULONG NewConnectionsCount,
1810 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1811 {
1812 ULONG Count;
1813 NTSTATUS Status;
1814 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1815
1816 DPRINT("KsFilterAddTopologyConnections\n");
1817
1818 ASSERT(This->Filter.Descriptor);
1819 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1820
1821
1822 /* modify connections array */
1823 Status = _KsEdit(This->Filter.Bag,
1824 (PVOID*)&This->Filter.Descriptor->Connections,
1825 Count * sizeof(KSTOPOLOGY_CONNECTION),
1826 This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1827 0);
1828
1829 if (!NT_SUCCESS(Status))
1830 {
1831 /* failed */
1832 DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
1833 return Status;
1834 }
1835
1836 /* FIXME verify connections */
1837
1838 /* copy new connections */
1839 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
1840 NewTopologyConnections,
1841 NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
1842
1843 /* update topology */
1844 This->Topology.TopologyConnectionsCount += NewConnectionsCount;
1845 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
1846 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1847
1848 return Status;
1849 }
1850
1851 /*
1852 @implemented
1853 */
1854 KSDDKAPI
1855 VOID
1856 NTAPI
1857 KsFilterAttemptProcessing(
1858 IN PKSFILTER Filter,
1859 IN BOOLEAN Asynchronous)
1860 {
1861 PKSGATE Gate;
1862 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1863
1864 /* get gate */
1865 Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
1866
1867 if (!KsGateCaptureThreshold(Gate))
1868 {
1869 /* filter control gate is closed */
1870 return;
1871 }
1872 DPRINT1("processing\n");
1873 /* try initiate processing */
1874 This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
1875 }
1876
1877 /*
1878 @unimplemented
1879 */
1880 KSDDKAPI
1881 NTSTATUS
1882 NTAPI
1883 KsFilterCreateNode (
1884 IN PKSFILTER Filter,
1885 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1886 OUT PULONG NodeID)
1887 {
1888 UNIMPLEMENTED
1889 return STATUS_NOT_IMPLEMENTED;
1890 }
1891
1892 /*
1893 @implemented
1894 */
1895 KSDDKAPI
1896 NTSTATUS
1897 NTAPI
1898 KsFilterCreatePinFactory (
1899 IN PKSFILTER Filter,
1900 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1901 OUT PULONG PinID)
1902 {
1903 ULONG Count;
1904 NTSTATUS Status;
1905 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1906
1907 DPRINT("KsFilterCreatePinFactory\n");
1908
1909 /* calculate new count */
1910 Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
1911
1912 /* sanity check */
1913 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1914
1915 /* modify pin descriptors ex array */
1916 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 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 pin instance count array */
1925 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * 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 /* modify first pin array */
1934 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PVOID) * Count, sizeof(PVOID) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1935 if (!NT_SUCCESS(Status))
1936 {
1937 /* failed */
1938 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1939 return Status;
1940 }
1941
1942 /* add new pin factory */
1943 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
1944
1945 /* allocate process pin index */
1946 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
1947 sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1948
1949 if (!NT_SUCCESS(Status))
1950 {
1951 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
1952 return Status;
1953 }
1954
1955 /* store new pin id */
1956 *PinID = This->Filter.Descriptor->PinDescriptorsCount;
1957
1958 /* increment pin descriptor count */
1959 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
1960
1961
1962 DPRINT("KsFilterCreatePinFactory done\n");
1963 return STATUS_SUCCESS;
1964
1965 }
1966
1967 /*
1968 @unimplemented
1969 */
1970 KSDDKAPI
1971 PKSGATE
1972 NTAPI
1973 KsFilterGetAndGate(
1974 IN PKSFILTER Filter)
1975 {
1976 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1977
1978 /* return and-gate */
1979 return &This->Gate;
1980 }
1981
1982 /*
1983 @implemented
1984 */
1985 KSDDKAPI
1986 ULONG
1987 NTAPI
1988 KsFilterGetChildPinCount(
1989 IN PKSFILTER Filter,
1990 IN ULONG PinId)
1991 {
1992 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1993
1994 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
1995 {
1996 /* index is out of bounds */
1997 return 0;
1998 }
1999 /* return pin instance count */
2000 return This->PinInstanceCount[PinId];
2001 }
2002
2003 /*
2004 @implemented
2005 */
2006 KSDDKAPI
2007 PKSPIN
2008 NTAPI
2009 KsFilterGetFirstChildPin(
2010 IN PKSFILTER Filter,
2011 IN ULONG PinId)
2012 {
2013 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2014
2015 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
2016 {
2017 /* index is out of bounds */
2018 return NULL;
2019 }
2020
2021 /* return first pin index */
2022 return This->FirstPin[PinId];
2023 }
2024
2025 /*
2026 @implemented
2027 */
2028 KSDDKAPI
2029 VOID
2030 NTAPI
2031 KsFilterRegisterPowerCallbacks(
2032 IN PKSFILTER Filter,
2033 IN PFNKSFILTERPOWER Sleep OPTIONAL,
2034 IN PFNKSFILTERPOWER Wake OPTIONAL)
2035 {
2036 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2037
2038 This->Sleep = Sleep;
2039 This->Wake = Wake;
2040 }
2041
2042 /*
2043 @implemented
2044 */
2045 KSDDKAPI
2046 PKSFILTER
2047 NTAPI
2048 KsGetFilterFromIrp(
2049 IN PIRP Irp)
2050 {
2051 PIO_STACK_LOCATION IoStack;
2052 PKSIOBJECT_HEADER ObjectHeader;
2053
2054 DPRINT("KsGetFilterFromIrp\n");
2055
2056 /* get current irp stack location */
2057 IoStack = IoGetCurrentIrpStackLocation(Irp);
2058
2059 /* sanity check */
2060 ASSERT(IoStack->FileObject);
2061
2062 /* get object header */
2063 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2064
2065 if (ObjectHeader->Type == KsObjectTypeFilter)
2066 {
2067 /* irp is targeted at the filter */
2068 return (PKSFILTER)ObjectHeader->ObjectType;
2069 }
2070 else if (ObjectHeader->Type == KsObjectTypePin)
2071 {
2072 /* irp is for a pin */
2073 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
2074 }
2075 else
2076 {
2077 /* irp is unappropiate to retrieve a filter */
2078 return NULL;
2079 }
2080 }