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