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