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