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