bcac218e84862b909e1fe7341b69ee4a7051e9d1
[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 /* get filter instance */
782 FilterInstance = Filter->lpVtbl->GetStruct(Filter);
783
784
785 /* sanity check */
786 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
787 ASSERT(FilterInstance);
788 ASSERT(FilterInstance->Descriptor);
789 ASSERT(FilterInstance->Descriptor->AutomationTable);
790
791 RtlStringFromGUID(&Property->Set, &GuidString);
792 DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
793 RtlFreeUnicodeString(&GuidString);
794
795 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
796 {
797 const KSMETHOD_SET *MethodSet = NULL;
798 ULONG MethodItemSize = 0;
799
800 /* check if the driver supports method sets */
801 if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
802 {
803 SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
804 MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
805 MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
806 }
807
808 /* call method set handler */
809 Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
810 }
811 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
812 {
813 const KSPROPERTY_SET *PropertySet = NULL;
814 ULONG PropertyItemSize = 0;
815
816 /* check if the driver supports method sets */
817 if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
818 {
819 SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
820 PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
821 PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
822 }
823
824 /* needed for our property handlers */
825 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
826
827 /* call property handler */
828 Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
829 }
830 else
831 {
832 /* sanity check */
833 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
834 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
835
836 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
837 {
838 /* call enable event handlers */
839 Status = KspEnableEvent(Irp,
840 FilterInstance->Descriptor->AutomationTable->EventSetsCount,
841 (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
842 &This->Header.EventList,
843 KSEVENTS_SPINLOCK,
844 (PVOID)&This->Header.EventListLock,
845 NULL,
846 FilterInstance->Descriptor->AutomationTable->EventItemSize);
847 }
848 else
849 {
850 /* disable event handler */
851 Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
852 }
853 }
854
855 RtlStringFromGUID(&Property->Set, &GuidString);
856 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);
857 RtlFreeUnicodeString(&GuidString);
858
859 /* release filter */
860 Filter->lpVtbl->Release(Filter);
861
862 if (Status != STATUS_PENDING)
863 {
864 Irp->IoStatus.Status = Status;
865 IoCompleteRequest(Irp, IO_NO_INCREMENT);
866 }
867
868 /* done */
869 return Status;
870 }
871
872 static KSDISPATCH_TABLE DispatchTable =
873 {
874 IKsFilter_DispatchDeviceIoControl,
875 KsDispatchInvalidDeviceRequest,
876 KsDispatchInvalidDeviceRequest,
877 KsDispatchInvalidDeviceRequest,
878 IKsFilter_DispatchClose,
879 KsDispatchQuerySecurity,
880 KsDispatchSetSecurity,
881 KsDispatchFastIoDeviceControlFailure,
882 KsDispatchFastReadFailure,
883 KsDispatchFastReadFailure,
884 };
885
886
887 NTSTATUS
888 IKsFilter_CreateDescriptors(
889 IKsFilterImpl * This,
890 KSFILTER_DESCRIPTOR* FilterDescriptor)
891 {
892 ULONG Index = 0;
893 NTSTATUS Status;
894
895 /* initialize pin descriptors */
896 This->FirstPin = NULL;
897 This->PinInstanceCount = NULL;
898 This->PinDescriptors = NULL;
899 This->PinDescriptorsEx = NULL;
900 This->ProcessPinIndex = NULL;
901 This->PinDescriptorCount = 0;
902
903 /* initialize topology descriptor */
904 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
905 This->Topology.Categories = FilterDescriptor->Categories;
906 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
907 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
908 This->Topology.TopologyConnections = FilterDescriptor->Connections;
909
910 /* are there any templates */
911 if (FilterDescriptor->PinDescriptorsCount)
912 {
913 /* sanity check */
914 ASSERT(FilterDescriptor->PinDescriptors);
915
916 /* FIXME handle variable sized pin descriptors */
917 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
918
919 /* store pin descriptors ex */
920 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount,
921 sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, 0);
922
923 if (!NT_SUCCESS(Status))
924 {
925 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
926 return Status;
927 }
928
929 /* store pin descriptors */
930 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount,
931 sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, 0);
932
933 if (!NT_SUCCESS(Status))
934 {
935 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
936 return Status;
937 }
938
939 /* store pin instance count ex */
940 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
941 sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
942
943 if (!NT_SUCCESS(Status))
944 {
945 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
946 return Status;
947 }
948
949 /* store instantiated pin arrays */
950 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
951 sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
952
953 if (!NT_SUCCESS(Status))
954 {
955 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
956 return Status;
957 }
958
959 /* add new pin factory */
960 RtlMoveMemory(This->PinDescriptorsEx, FilterDescriptor->PinDescriptors, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount);
961
962 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
963 {
964 RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
965 }
966
967 /* allocate process pin index */
968 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
969 sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
970
971 if (!NT_SUCCESS(Status))
972 {
973 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
974 return Status;
975 }
976
977 /* store new pin descriptor count */
978 This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
979
980 }
981
982 if (FilterDescriptor->NodeDescriptorsCount)
983 {
984 /* sanity check */
985 ASSERT(FilterDescriptor->NodeDescriptors);
986
987 /* FIXME handle variable sized node descriptors */
988 ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
989
990 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
991 /* allocate topology node types array */
992 if (!This->Topology.TopologyNodes)
993 {
994 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
995 return STATUS_INSUFFICIENT_RESOURCES;
996 }
997
998 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
999 /* allocate topology names array */
1000 if (!This->Topology.TopologyNodesNames)
1001 {
1002 FreeItem((PVOID)This->Topology.TopologyNodes);
1003 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1004 return STATUS_INSUFFICIENT_RESOURCES;
1005 }
1006
1007 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1008 for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
1009 {
1010 DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
1011
1012 /* copy topology type */
1013 if (FilterDescriptor->NodeDescriptors[Index].Type)
1014 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
1015
1016 /* copy topology name */
1017 if (FilterDescriptor->NodeDescriptors[Index].Name)
1018 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
1019 }
1020 }
1021 /* done! */
1022 return STATUS_SUCCESS;
1023 }
1024
1025 NTSTATUS
1026 IKsFilter_CopyFilterDescriptor(
1027 IKsFilterImpl * This,
1028 const KSFILTER_DESCRIPTOR* FilterDescriptor)
1029 {
1030 NTSTATUS Status;
1031 KSAUTOMATION_TABLE AutomationTable;
1032
1033 This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
1034 if (!This->Filter.Descriptor)
1035 return STATUS_INSUFFICIENT_RESOURCES;
1036
1037 Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
1038 if (!NT_SUCCESS(Status))
1039 {
1040 FreeItem((PVOID)This->Filter.Descriptor);
1041 This->Filter.Descriptor = NULL;
1042 return STATUS_INSUFFICIENT_RESOURCES;
1043 }
1044
1045 /* copy filter descriptor fields */
1046 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
1047
1048 /* zero automation table */
1049 RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
1050
1051 /* setup filter property sets */
1052 AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
1053 AutomationTable.PropertySetsCount = 2;
1054 AutomationTable.PropertySets = FilterPropertySet;
1055
1056 /* merge filter automation table */
1057 Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
1058
1059 return Status;
1060 }
1061
1062
1063 VOID
1064 IKsFilter_AddPin(
1065 PKSFILTER Filter,
1066 PKSPIN Pin)
1067 {
1068 PKSPIN NextPin, CurPin;
1069 PKSBASIC_HEADER BasicHeader;
1070 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1071
1072 /* sanity check */
1073 ASSERT(Pin->Id < This->PinDescriptorCount);
1074
1075 if (This->FirstPin[Pin->Id] == NULL)
1076 {
1077 /* welcome first pin */
1078 This->FirstPin[Pin->Id] = Pin;
1079 This->PinInstanceCount[Pin->Id]++;
1080 return;
1081 }
1082
1083 /* get first pin */
1084 CurPin = This->FirstPin[Pin->Id];
1085
1086 do
1087 {
1088 /* get next instantiated pin */
1089 NextPin = KsPinGetNextSiblingPin(CurPin);
1090 if (!NextPin)
1091 break;
1092
1093 NextPin = CurPin;
1094
1095 }while(NextPin != NULL);
1096
1097 /* get basic header */
1098 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
1099
1100 /* store pin */
1101 BasicHeader->Next.Pin = Pin;
1102 }
1103
1104 VOID
1105 IKsFilter_RemovePin(
1106 PKSFILTER Filter,
1107 PKSPIN Pin)
1108 {
1109 PKSPIN NextPin, CurPin, LastPin;
1110 PKSBASIC_HEADER BasicHeader;
1111 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1112
1113 /* sanity check */
1114 ASSERT(Pin->Id < This->PinDescriptorCount);
1115
1116 /* get first pin */
1117 CurPin = This->FirstPin[Pin->Id];
1118
1119 LastPin = NULL;
1120 do
1121 {
1122 /* get next instantiated pin */
1123 NextPin = KsPinGetNextSiblingPin(CurPin);
1124
1125 if (CurPin == Pin)
1126 {
1127 if (LastPin)
1128 {
1129 /* get basic header of last pin */
1130 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
1131
1132 BasicHeader->Next.Pin = NextPin;
1133 }
1134 else
1135 {
1136 /* erase last pin */
1137 This->FirstPin[Pin->Id] = NextPin;
1138 }
1139 /* decrement pin instance count */
1140 This->PinInstanceCount[Pin->Id]--;
1141 return;
1142 }
1143
1144 if (!NextPin)
1145 break;
1146
1147 LastPin = CurPin;
1148 NextPin = CurPin;
1149
1150 }while(NextPin != NULL);
1151
1152 /* pin not found */
1153 ASSERT(0);
1154 }
1155
1156
1157 NTSTATUS
1158 NTAPI
1159 IKsFilter_DispatchCreatePin(
1160 IN PDEVICE_OBJECT DeviceObject,
1161 IN PIRP Irp)
1162 {
1163 IKsFilterImpl * This;
1164 PKSOBJECT_CREATE_ITEM CreateItem;
1165 PKSPIN_CONNECT Connect;
1166 NTSTATUS Status;
1167
1168 DPRINT("IKsFilter_DispatchCreatePin\n");
1169
1170 /* get the create item */
1171 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1172
1173 /* get the filter object */
1174 This = (IKsFilterImpl*)CreateItem->Context;
1175
1176 /* sanity check */
1177 ASSERT(This->Header.Type == KsObjectTypeFilter);
1178
1179 /* acquire control mutex */
1180 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1181
1182 /* now validate the connect request */
1183 Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect);
1184
1185 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
1186
1187 if (NT_SUCCESS(Status))
1188 {
1189 /* sanity check */
1190 ASSERT(Connect->PinId < This->PinDescriptorCount);
1191
1192 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1193 This->PinInstanceCount[Connect->PinId],
1194 This->PinDescriptorsEx[Connect->PinId].InstancesPossible);
1195
1196 if (This->PinInstanceCount[Connect->PinId] < This->PinDescriptorsEx[Connect->PinId].InstancesPossible)
1197 {
1198 /* create the pin */
1199 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[Connect->PinId]);
1200
1201 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status);
1202 }
1203 else
1204 {
1205 /* maximum instance count reached, bye-bye */
1206 Status = STATUS_UNSUCCESSFUL;
1207 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->PinDescriptorsEx[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1208 }
1209 }
1210
1211 /* release control mutex */
1212 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1213
1214 if (Status != STATUS_PENDING)
1215 {
1216 /* complete request */
1217 Irp->IoStatus.Status = Status;
1218 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1219 }
1220
1221 /* done */
1222 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1223 return Status;
1224 }
1225
1226 NTSTATUS
1227 NTAPI
1228 IKsFilter_DispatchCreateNode(
1229 IN PDEVICE_OBJECT DeviceObject,
1230 IN PIRP Irp)
1231 {
1232 UNIMPLEMENTED
1233 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1234 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1235 return STATUS_UNSUCCESSFUL;
1236 }
1237
1238
1239 VOID
1240 IKsFilter_AttachFilterToFilterFactory(
1241 IKsFilterImpl * This,
1242 PKSFILTERFACTORY FilterFactory)
1243 {
1244 PKSBASIC_HEADER BasicHeader;
1245 PKSFILTER Filter;
1246
1247
1248 /* get filter factory basic header */
1249 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1250
1251 /* sanity check */
1252 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1253
1254 if (BasicHeader->FirstChild.FilterFactory == NULL)
1255 {
1256 /* welcome first instantiated filter */
1257 BasicHeader->FirstChild.Filter = &This->Filter;
1258 return;
1259 }
1260
1261 /* set to first entry */
1262 Filter = BasicHeader->FirstChild.Filter;
1263
1264 do
1265 {
1266 /* get basic header */
1267 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1268 /* sanity check */
1269 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1270
1271 if (BasicHeader->Next.Filter)
1272 {
1273 /* iterate to next filter factory */
1274 Filter = BasicHeader->Next.Filter;
1275 }
1276 else
1277 {
1278 /* found last entry */
1279 break;
1280 }
1281 }while(TRUE);
1282
1283 /* attach filter factory */
1284 BasicHeader->Next.Filter = &This->Filter;
1285 }
1286
1287 VOID
1288 IKsFilter_RemoveFilterFromFilterFactory(
1289 IKsFilterImpl * This,
1290 PKSFILTERFACTORY FilterFactory)
1291 {
1292 PKSBASIC_HEADER BasicHeader;
1293 PKSFILTER Filter, LastFilter;
1294
1295 /* get filter factory basic header */
1296 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1297
1298 /* sanity check */
1299 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1300 ASSERT(BasicHeader->FirstChild.Filter != NULL);
1301
1302
1303 /* set to first entry */
1304 Filter = BasicHeader->FirstChild.Filter;
1305 LastFilter = NULL;
1306
1307 do
1308 {
1309 if (Filter == &This->Filter)
1310 {
1311 if (LastFilter)
1312 {
1313 /* get basic header */
1314 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
1315 /* remove filter instance */
1316 BasicHeader->Next.Filter = This->Header.Next.Filter;
1317 break;
1318 }
1319 else
1320 {
1321 /* remove filter instance */
1322 BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
1323 break;
1324 }
1325 }
1326
1327 /* get basic header */
1328 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1329 /* sanity check */
1330 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1331
1332 LastFilter = Filter;
1333 if (BasicHeader->Next.Filter)
1334 {
1335 /* iterate to next filter factory */
1336 Filter = BasicHeader->Next.Filter;
1337 }
1338 else
1339 {
1340 /* filter is not in list */
1341 ASSERT(0);
1342 break;
1343 }
1344 }while(TRUE);
1345 }
1346
1347 NTSTATUS
1348 NTAPI
1349 KspCreateFilter(
1350 IN PDEVICE_OBJECT DeviceObject,
1351 IN PIRP Irp,
1352 IN IKsFilterFactory *iface)
1353 {
1354 IKsFilterImpl * This;
1355 IKsDevice *KsDevice;
1356 PKSFILTERFACTORY Factory;
1357 PIO_STACK_LOCATION IoStack;
1358 PDEVICE_EXTENSION DeviceExtension;
1359 NTSTATUS Status;
1360 PKSOBJECT_CREATE_ITEM CreateItem;
1361
1362 /* get device extension */
1363 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1364
1365 /* get the filter factory */
1366 Factory = iface->lpVtbl->GetStruct(iface);
1367
1368 if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
1369 {
1370 /* Sorry it just will not work */
1371 return STATUS_UNSUCCESSFUL;
1372 }
1373
1374 /* allocate filter instance */
1375 This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1376 if (!This)
1377 {
1378 DPRINT("KspCreateFilter OutOfMemory\n");
1379 return STATUS_INSUFFICIENT_RESOURCES;
1380 }
1381
1382 /* initialize object bag */
1383 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1384 if (!This->Filter.Bag)
1385 {
1386 /* no memory */
1387 FreeItem(This);
1388 DPRINT("KspCreateFilter OutOfMemory\n");
1389 return STATUS_INSUFFICIENT_RESOURCES;
1390 }
1391 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1392 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1393
1394 /* copy filter descriptor */
1395 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1396 if (!NT_SUCCESS(Status))
1397 {
1398 /* not enough memory */
1399 FreeItem(This->Filter.Bag);
1400 FreeItem(This);
1401 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1402 return STATUS_INSUFFICIENT_RESOURCES;
1403 }
1404
1405 /* get current irp stack */
1406 IoStack = IoGetCurrentIrpStackLocation(Irp);
1407
1408 /* allocate create items */
1409 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1410 if (!CreateItem)
1411 {
1412 /* no memory */
1413 FreeItem(This->Filter.Bag);
1414 FreeItem(This);
1415 DPRINT("KspCreateFilter OutOfMemory\n");
1416 return STATUS_INSUFFICIENT_RESOURCES;
1417 }
1418
1419 DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags);
1420
1421 /* initialize pin create item */
1422 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1423 CreateItem[0].Context = (PVOID)This;
1424 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1425 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1426 /* initialize node create item */
1427 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1428 CreateItem[1].Context = (PVOID)This;
1429 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1430 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1431
1432
1433 /* initialize filter instance */
1434 This->ref = 1;
1435 This->lpVtbl = &vt_IKsFilter;
1436 This->lpVtblKsControl = &vt_IKsControl;
1437
1438 This->Factory = Factory;
1439 This->FilterFactory = iface;
1440 This->FileObject = IoStack->FileObject;
1441 KeInitializeMutex(&This->ProcessingMutex, 0);
1442 /* initialize basic header */
1443 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1444 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1445 This->Header.Type = KsObjectTypeFilter;
1446 This->Header.ControlMutex = &This->ControlMutex;
1447 KeInitializeMutex(This->Header.ControlMutex, 0);
1448 InitializeListHead(&This->Header.EventList);
1449 KeInitializeSpinLock(&This->Header.EventListLock);
1450
1451 /* allocate the stream descriptors */
1452 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1453 if (!NT_SUCCESS(Status))
1454 {
1455 /* what can go wrong, goes wrong */
1456 FreeItem(This);
1457 FreeItem(CreateItem);
1458 DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1459 return Status;
1460 }
1461
1462 /* does the filter have a filter dispatch */
1463 if (Factory->FilterDescriptor->Dispatch)
1464 {
1465 /* does it have a create routine */
1466 if (Factory->FilterDescriptor->Dispatch->Create)
1467 {
1468 /* now let driver initialize the filter instance */
1469
1470 ASSERT(This->Header.KsDevice);
1471 ASSERT(This->Header.KsDevice->Started);
1472 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1473
1474 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1475 {
1476 /* driver failed to initialize */
1477 DPRINT1("Driver: Status %x\n", Status);
1478
1479 /* free filter instance */
1480 FreeItem(This);
1481 FreeItem(CreateItem);
1482 return Status;
1483 }
1484 }
1485 }
1486
1487 /* now allocate the object header */
1488 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1489 if (!NT_SUCCESS(Status))
1490 {
1491 /* failed to allocate object header */
1492 DPRINT1("Failed to allocate object header %x\n", Status);
1493
1494 return Status;
1495 }
1496
1497 /* initialize object header extra fields */
1498 This->ObjectHeader->Type = KsObjectTypeFilter;
1499 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1500 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1501
1502 /* attach filter to filter factory */
1503 IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1504
1505 /* completed initialization */
1506 DPRINT("KspCreateFilter done %lx\n", Status);
1507 return Status;
1508 }
1509
1510 /*
1511 @implemented
1512 */
1513 KSDDKAPI
1514 VOID
1515 NTAPI
1516 KsFilterAcquireProcessingMutex(
1517 IN PKSFILTER Filter)
1518 {
1519 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1520
1521 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1522 }
1523
1524 /*
1525 @implemented
1526 */
1527 KSDDKAPI
1528 VOID
1529 NTAPI
1530 KsFilterReleaseProcessingMutex(
1531 IN PKSFILTER Filter)
1532 {
1533 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1534
1535 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1536 }
1537
1538
1539 /*
1540 @implemented
1541 */
1542 KSDDKAPI
1543 NTSTATUS
1544 NTAPI
1545 KsFilterAddTopologyConnections (
1546 IN PKSFILTER Filter,
1547 IN ULONG NewConnectionsCount,
1548 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1549 {
1550 ULONG Count;
1551 KSTOPOLOGY_CONNECTION * Connections;
1552 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1553
1554 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1555
1556 /* allocate array */
1557 Connections = AllocateItem(NonPagedPool, Count * sizeof(KSTOPOLOGY_CONNECTION));
1558 if (!Connections)
1559 return STATUS_INSUFFICIENT_RESOURCES;
1560
1561 /* FIXME verify connections */
1562
1563 if (This->Filter.Descriptor->ConnectionsCount)
1564 {
1565 /* copy old connections */
1566 RtlMoveMemory(Connections, This->Filter.Descriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * This->Filter.Descriptor->ConnectionsCount);
1567 }
1568
1569 /* add new connections */
1570 RtlMoveMemory((PVOID)(Connections + This->Filter.Descriptor->ConnectionsCount), NewTopologyConnections, NewConnectionsCount);
1571
1572 /* add the new connections */
1573 RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */
1574
1575 /* free old connections array */
1576 if (This->Filter.Descriptor->ConnectionsCount)
1577 {
1578 FreeItem((PVOID)This->Filter.Descriptor->Connections);
1579 }
1580
1581 /* brain-dead gcc hack */
1582 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*));
1583
1584 return STATUS_SUCCESS;
1585 }
1586
1587 /*
1588 @unimplemented
1589 */
1590 KSDDKAPI
1591 VOID
1592 NTAPI
1593 KsFilterAttemptProcessing(
1594 IN PKSFILTER Filter,
1595 IN BOOLEAN Asynchronous)
1596 {
1597 UNIMPLEMENTED
1598 }
1599
1600 /*
1601 @unimplemented
1602 */
1603 KSDDKAPI
1604 NTSTATUS
1605 NTAPI
1606 KsFilterCreateNode (
1607 IN PKSFILTER Filter,
1608 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1609 OUT PULONG NodeID)
1610 {
1611 UNIMPLEMENTED
1612 return STATUS_NOT_IMPLEMENTED;
1613 }
1614
1615 /*
1616 @implemented
1617 */
1618 KSDDKAPI
1619 NTSTATUS
1620 NTAPI
1621 KsFilterCreatePinFactory (
1622 IN PKSFILTER Filter,
1623 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1624 OUT PULONG PinID)
1625 {
1626 ULONG Count;
1627 NTSTATUS Status;
1628 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1629
1630 DPRINT("KsFilterCreatePinFactory\n");
1631
1632 /* calculate new count */
1633 Count = This->PinDescriptorCount + 1;
1634
1635 /* sanity check */
1636 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1637
1638 /* allocate pin descriptors ex array */
1639 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, Count * sizeof(KSPIN_DESCRIPTOR_EX), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR_EX), 0);
1640 if (!NT_SUCCESS(Status))
1641 {
1642 /* failed */
1643 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1644 return Status;
1645 }
1646
1647 /* allocate pin descriptors array */
1648 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR), 0);
1649 if (!NT_SUCCESS(Status))
1650 {
1651 /* failed */
1652 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1653 return Status;
1654 }
1655
1656
1657 /* allocate pin instance count array */
1658 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->PinDescriptorCount, 0);
1659 if (!NT_SUCCESS(Status))
1660 {
1661 /* failed */
1662 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1663 return Status;
1664 }
1665
1666 /* allocate first pin array */
1667 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->PinDescriptorCount, 0);
1668 if (!NT_SUCCESS(Status))
1669 {
1670 /* failed */
1671 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1672 return Status;
1673 }
1674
1675 /* add new pin factory */
1676 RtlMoveMemory(&This->PinDescriptorsEx[This->PinDescriptorCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
1677 RtlMoveMemory(&This->PinDescriptors[This->PinDescriptorCount], &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1678
1679
1680 /* allocate process pin index */
1681 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
1682 sizeof(KSPROCESSPIN_INDEXENTRY) * This->PinDescriptorCount, 0);
1683
1684 if (!NT_SUCCESS(Status))
1685 {
1686 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
1687 return Status;
1688 }
1689
1690 /* store new pin id */
1691 *PinID = This->PinDescriptorCount;
1692
1693 /* increment pin descriptor count */
1694 This->PinDescriptorCount++;
1695
1696
1697 DPRINT("KsFilterCreatePinFactory done\n");
1698 return STATUS_SUCCESS;
1699
1700 }
1701
1702 /*
1703 @unimplemented
1704 */
1705 KSDDKAPI
1706 PKSGATE
1707 NTAPI
1708 KsFilterGetAndGate(
1709 IN PKSFILTER Filter)
1710 {
1711 UNIMPLEMENTED
1712 return NULL;
1713 }
1714
1715 /*
1716 @implemented
1717 */
1718 KSDDKAPI
1719 ULONG
1720 NTAPI
1721 KsFilterGetChildPinCount(
1722 IN PKSFILTER Filter,
1723 IN ULONG PinId)
1724 {
1725 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1726
1727 if (PinId >= This->PinDescriptorCount)
1728 {
1729 /* index is out of bounds */
1730 return 0;
1731 }
1732 /* return pin instance count */
1733 return This->PinInstanceCount[PinId];
1734 }
1735
1736 /*
1737 @implemented
1738 */
1739 KSDDKAPI
1740 PKSPIN
1741 NTAPI
1742 KsFilterGetFirstChildPin(
1743 IN PKSFILTER Filter,
1744 IN ULONG PinId)
1745 {
1746 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1747
1748 if (PinId >= This->PinDescriptorCount)
1749 {
1750 /* index is out of bounds */
1751 return NULL;
1752 }
1753
1754 /* return first pin index */
1755 return This->FirstPin[PinId];
1756 }
1757
1758 /*
1759 @implemented
1760 */
1761 KSDDKAPI
1762 VOID
1763 NTAPI
1764 KsFilterRegisterPowerCallbacks(
1765 IN PKSFILTER Filter,
1766 IN PFNKSFILTERPOWER Sleep OPTIONAL,
1767 IN PFNKSFILTERPOWER Wake OPTIONAL)
1768 {
1769 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1770
1771 This->Sleep = Sleep;
1772 This->Wake = Wake;
1773 }
1774
1775 /*
1776 @implemented
1777 */
1778 KSDDKAPI
1779 PKSFILTER
1780 NTAPI
1781 KsGetFilterFromIrp(
1782 IN PIRP Irp)
1783 {
1784 PIO_STACK_LOCATION IoStack;
1785 PKSIOBJECT_HEADER ObjectHeader;
1786
1787 DPRINT("KsGetFilterFromIrp\n");
1788
1789 /* get current irp stack location */
1790 IoStack = IoGetCurrentIrpStackLocation(Irp);
1791
1792 /* sanity check */
1793 ASSERT(IoStack->FileObject);
1794
1795 /* get object header */
1796 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1797
1798 if (ObjectHeader->Type == KsObjectTypeFilter)
1799 {
1800 /* irp is targeted at the filter */
1801 return (PKSFILTER)ObjectHeader->ObjectType;
1802 }
1803 else if (ObjectHeader->Type == KsObjectTypePin)
1804 {
1805 /* irp is for a pin */
1806 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
1807 }
1808 else
1809 {
1810 /* irp is unappropiate to retrieve a filter */
1811 return NULL;
1812 }
1813 }