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