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