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