- Implement KsAddEvent, KsDefaultAddEventHandler, KsPinAttachAndGate, KsPinAttachOrGa...
[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 (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 /* now release the acquired interface */
444 Filter->lpVtbl->Release(Filter);
445
446 /* free object header */
447 KsFreeObjectHeader(This->ObjectHeader);
448 }
449
450 /* done */
451 return Status;
452 }
453
454 NTSTATUS
455 KspHandlePropertyInstances(
456 IN PIO_STATUS_BLOCK IoStatus,
457 IN PKSIDENTIFIER Request,
458 IN OUT PVOID Data,
459 IN IKsFilterImpl * This,
460 IN BOOL Global)
461 {
462 KSPIN_CINSTANCES * Instances;
463 KSP_PIN * Pin = (KSP_PIN*)Request;
464
465 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
466 {
467 /* no filter / pin descriptor */
468 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
469 return STATUS_NOT_IMPLEMENTED;
470 }
471
472 /* ignore custom structs for now */
473 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
474 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
475
476 Instances = (KSPIN_CINSTANCES*)Data;
477 /* max instance count */
478 Instances->PossibleCount = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible;
479 /* current instance count */
480 Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
481
482 IoStatus->Information = sizeof(KSPIN_CINSTANCES);
483 IoStatus->Status = STATUS_SUCCESS;
484 return STATUS_SUCCESS;
485 }
486
487 NTSTATUS
488 KspHandleNecessaryPropertyInstances(
489 IN PIO_STATUS_BLOCK IoStatus,
490 IN PKSIDENTIFIER Request,
491 IN OUT PVOID Data,
492 IN IKsFilterImpl * This)
493 {
494 PULONG Result;
495 KSP_PIN * Pin = (KSP_PIN*)Request;
496
497 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
498 {
499 /* no filter / pin descriptor */
500 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
501 return STATUS_NOT_IMPLEMENTED;
502 }
503
504 /* ignore custom structs for now */
505 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
506 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
507
508 Result = (PULONG)Data;
509 *Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
510
511 IoStatus->Information = sizeof(ULONG);
512 IoStatus->Status = STATUS_SUCCESS;
513 return STATUS_SUCCESS;
514 }
515
516 NTSTATUS
517 KspHandleDataIntersection(
518 IN PIRP Irp,
519 IN PIO_STATUS_BLOCK IoStatus,
520 IN PKSIDENTIFIER Request,
521 IN OUT PVOID Data,
522 IN ULONG DataLength,
523 IN IKsFilterImpl * This)
524 {
525 PKSMULTIPLE_ITEM MultipleItem;
526 PKSDATARANGE DataRange;
527 NTSTATUS Status = STATUS_NO_MATCH;
528 ULONG Index, Length;
529 KSP_PIN * Pin = (KSP_PIN*)Request;
530
531 /* Access parameters */
532 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
533 DataRange = (PKSDATARANGE)(MultipleItem + 1);
534
535 if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
536 {
537 /* no filter / pin descriptor */
538 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
539 return STATUS_NOT_IMPLEMENTED;
540 }
541
542 /* ignore custom structs for now */
543 ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
544 ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
545
546 if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
547 This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
548 This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
549 {
550 /* no driver supported intersect handler / no provided data ranges */
551 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
552 return STATUS_NOT_IMPLEMENTED;
553 }
554
555 for(Index = 0; Index < MultipleItem->Count; Index++)
556 {
557 /* Call miniport's properitary handler */
558 Status = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler(NULL, /* context */
559 Irp,
560 Pin,
561 DataRange,
562 (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges,
563 DataLength,
564 Data,
565 &Length);
566
567 if (Status == STATUS_SUCCESS)
568 {
569 IoStatus->Information = Length;
570 break;
571 }
572 DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
573 }
574
575 IoStatus->Status = Status;
576 return Status;
577 }
578
579 NTSTATUS
580 NTAPI
581 KspPinPropertyHandler(
582 IN PIRP Irp,
583 IN PKSIDENTIFIER Request,
584 IN OUT PVOID Data)
585 {
586 PIO_STACK_LOCATION IoStack;
587 IKsFilterImpl * This;
588 NTSTATUS Status = STATUS_UNSUCCESSFUL;
589
590 /* get filter implementation */
591 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
592
593 /* get current stack location */
594 IoStack = IoGetCurrentIrpStackLocation(Irp);
595
596 switch(Request->Id)
597 {
598 case KSPROPERTY_PIN_CTYPES:
599 case KSPROPERTY_PIN_DATAFLOW:
600 case KSPROPERTY_PIN_DATARANGES:
601 case KSPROPERTY_PIN_INTERFACES:
602 case KSPROPERTY_PIN_MEDIUMS:
603 case KSPROPERTY_PIN_COMMUNICATION:
604 case KSPROPERTY_PIN_CATEGORY:
605 case KSPROPERTY_PIN_NAME:
606 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
607 Status = KsPinPropertyHandler(Irp, Request, Data, This->PinDescriptorCount, This->PinDescriptors);
608 break;
609 case KSPROPERTY_PIN_GLOBALCINSTANCES:
610 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
611 break;
612 case KSPROPERTY_PIN_CINSTANCES:
613 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
614 break;
615 case KSPROPERTY_PIN_NECESSARYINSTANCES:
616 Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
617 break;
618
619 case KSPROPERTY_PIN_DATAINTERSECTION:
620 Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
621 break;
622 case KSPROPERTY_PIN_PHYSICALCONNECTION:
623 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
624 UNIMPLEMENTED
625 Status = STATUS_NOT_IMPLEMENTED;
626 break;
627 default:
628 UNIMPLEMENTED
629 Status = STATUS_UNSUCCESSFUL;
630 }
631
632 return Status;
633 }
634
635 NTSTATUS
636 FindPropertyHandler(
637 IN PIO_STATUS_BLOCK IoStatus,
638 IN KSPROPERTY_SET * FilterPropertySet,
639 IN ULONG FilterPropertySetCount,
640 IN PKSPROPERTY Property,
641 IN ULONG InputBufferLength,
642 IN ULONG OutputBufferLength,
643 OUT PFNKSHANDLER *PropertyHandler)
644 {
645 ULONG Index, ItemIndex;
646
647 for(Index = 0; Index < FilterPropertySetCount; Index++)
648 {
649 if (IsEqualGUIDAligned(&Property->Set, FilterPropertySet[Index].Set))
650 {
651 for(ItemIndex = 0; ItemIndex < FilterPropertySet[Index].PropertiesCount; ItemIndex++)
652 {
653 if (FilterPropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
654 {
655 if (Property->Flags & KSPROPERTY_TYPE_SET)
656 *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
657
658 if (Property->Flags & KSPROPERTY_TYPE_GET)
659 *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
660
661 if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
662 {
663 /* too small input buffer */
664 IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty;
665 IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
666 return STATUS_BUFFER_TOO_SMALL;
667 }
668
669 if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
670 {
671 /* too small output buffer */
672 IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinData;
673 IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
674 return STATUS_BUFFER_TOO_SMALL;
675 }
676 return STATUS_SUCCESS;
677 }
678 }
679 }
680 }
681 return STATUS_UNSUCCESSFUL;
682 }
683
684
685
686 NTSTATUS
687 NTAPI
688 IKsFilter_DispatchDeviceIoControl(
689 IN PDEVICE_OBJECT DeviceObject,
690 IN PIRP Irp)
691 {
692 PIO_STACK_LOCATION IoStack;
693 PFNKSHANDLER PropertyHandler = NULL;
694 IKsFilter * Filter;
695 IKsFilterImpl * This;
696 NTSTATUS Status;
697
698 /* obtain filter from object header */
699 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
700 if (!NT_SUCCESS(Status))
701 return Status;
702
703 /* get our real implementation */
704 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl);
705
706 /* current irp stack */
707 IoStack = IoGetCurrentIrpStackLocation(Irp);
708
709 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
710 {
711 UNIMPLEMENTED;
712
713 /* release filter interface */
714 Filter->lpVtbl->Release(Filter);
715
716 /* complete and forget irp */
717 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
718 IoCompleteRequest(Irp, IO_NO_INCREMENT);
719 return STATUS_NOT_IMPLEMENTED;
720 }
721
722 /* find a supported property handler */
723 Status = FindPropertyHandler(&Irp->IoStatus, FilterPropertySet, 2, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
724 if (NT_SUCCESS(Status))
725 {
726 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)This;
727 DPRINT("Calling property handler %p\n", PropertyHandler);
728 Status = PropertyHandler(Irp, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, Irp->UserBuffer);
729 }
730 else
731 {
732 /* call driver's property handler */
733 UNIMPLEMENTED
734 Status = STATUS_NOT_IMPLEMENTED;
735 }
736
737 Irp->IoStatus.Status = Status;
738 IoCompleteRequest(Irp, IO_NO_INCREMENT);
739
740 /* done */
741 return Status;
742 }
743
744 static KSDISPATCH_TABLE DispatchTable =
745 {
746 IKsFilter_DispatchDeviceIoControl,
747 KsDispatchInvalidDeviceRequest,
748 KsDispatchInvalidDeviceRequest,
749 KsDispatchInvalidDeviceRequest,
750 IKsFilter_DispatchClose,
751 KsDispatchQuerySecurity,
752 KsDispatchSetSecurity,
753 KsDispatchFastIoDeviceControlFailure,
754 KsDispatchFastReadFailure,
755 KsDispatchFastReadFailure,
756 };
757
758
759 NTSTATUS
760 IKsFilter_CreateDescriptors(
761 IKsFilterImpl * This,
762 KSFILTER_DESCRIPTOR* FilterDescriptor)
763 {
764 ULONG Index = 0;
765
766 /* initialize pin descriptors */
767 if (FilterDescriptor->PinDescriptorsCount)
768 {
769 /* allocate pin instance count array */
770 This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount);
771 if(!This->PinDescriptors)
772 {
773 return STATUS_INSUFFICIENT_RESOURCES;
774 }
775
776 /* allocate pin descriptor array */
777 This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount);
778 if(!This->PinDescriptors)
779 {
780 FreeItem(This->PinInstanceCount);
781 return STATUS_INSUFFICIENT_RESOURCES;
782 }
783
784 /* set pin count */
785 This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
786 /* now copy those pin descriptors over */
787 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
788 {
789 /* copy one pin per time */
790 RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
791 }
792 }
793
794 /* initialize topology descriptor */
795 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
796 This->Topology.Categories = FilterDescriptor->Categories;
797 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
798 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
799 This->Topology.TopologyConnections = FilterDescriptor->Connections;
800
801 if (This->Topology.TopologyNodesCount > 0)
802 {
803 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
804 /* allocate topology node types array */
805 if (!This->Topology.TopologyNodes)
806 return STATUS_INSUFFICIENT_RESOURCES;
807
808 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
809 /* allocate topology names array */
810 if (!This->Topology.TopologyNodesNames)
811 {
812 FreeItem((PVOID)This->Topology.TopologyNodes);
813 return STATUS_INSUFFICIENT_RESOURCES;
814 }
815
816 for(Index = 0; Index < This->Topology.TopologyNodesCount; Index++)
817 {
818 /* copy topology type */
819 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
820 /* copy topology name */
821 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
822 }
823 }
824
825 /* done! */
826 return STATUS_SUCCESS;
827 }
828
829 NTSTATUS
830 IKsFilter_CopyFilterDescriptor(
831 IKsFilterImpl * This,
832 const KSFILTER_DESCRIPTOR* FilterDescriptor)
833 {
834 This->Filter.Descriptor = (const KSFILTER_DESCRIPTOR*)AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
835 if (!This->Filter.Descriptor)
836 return STATUS_INSUFFICIENT_RESOURCES;
837
838 /* copy all fields */
839 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
840
841
842 /* perform deep copy of pin descriptors */
843 if (FilterDescriptor->PinDescriptorsCount)
844 {
845 KSPIN_DESCRIPTOR_EX * PinDescriptors = (KSPIN_DESCRIPTOR_EX *)AllocateItem(NonPagedPool, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
846
847
848 if (!PinDescriptors)
849 {
850 FreeItem((PVOID)This->Filter.Descriptor);
851 return STATUS_INSUFFICIENT_RESOURCES;
852 }
853 RtlMoveMemory((PVOID)PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
854
855 /* brain-dead gcc hack */
856 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptors, sizeof(PKSPIN_DESCRIPTOR_EX));
857
858 }
859
860 /* perform deep copy of node descriptors */
861 if (FilterDescriptor->NodeDescriptorsCount)
862 {
863 KSNODE_DESCRIPTOR* NodeDescriptor = AllocateItem(NonPagedPool, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
864 if (!NodeDescriptor)
865 {
866 if (This->Filter.Descriptor->PinDescriptors)
867 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
868 FreeItem((PVOID)This->Filter.Descriptor);
869 return STATUS_INSUFFICIENT_RESOURCES;
870 }
871 RtlMoveMemory((PVOID)NodeDescriptor, FilterDescriptor->NodeDescriptors, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
872
873 /* brain-dead gcc hack */
874 RtlMoveMemory((PVOID)&This->Filter.Descriptor->NodeDescriptors, NodeDescriptor, sizeof(PKSNODE_DESCRIPTOR));
875 }
876
877 /* perform deep copy of connections descriptors */
878 if (FilterDescriptor->NodeDescriptorsCount)
879 {
880 KSTOPOLOGY_CONNECTION* Connections = AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
881 if (!Connections)
882 {
883 if (This->Filter.Descriptor->PinDescriptors)
884 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
885
886 if (This->Filter.Descriptor->NodeDescriptors)
887 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
888
889 FreeItem((PVOID)This->Filter.Descriptor);
890 return STATUS_INSUFFICIENT_RESOURCES;
891 }
892
893 RtlMoveMemory((PVOID)Connections, FilterDescriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
894
895 /* brain-dead gcc hack */
896 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(PKSTOPOLOGY_CONNECTION));
897 }
898
899 return STATUS_SUCCESS;
900 }
901
902 NTSTATUS
903 NTAPI
904 IKsFilter_DispatchCreatePin(
905 IN PDEVICE_OBJECT DeviceObject,
906 IN PIRP Irp)
907 {
908 IKsFilterImpl * This;
909 PKSOBJECT_CREATE_ITEM CreateItem;
910 PKSPIN_CONNECT Connect;
911 NTSTATUS Status;
912
913 /* get the create item */
914 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
915
916 /* get the filter object */
917 This = (IKsFilterImpl*)CreateItem->Context;
918
919 /* acquire control mutex */
920 KeWaitForSingleObject(&This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
921
922 /* now validate the connect request */
923 Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect);
924
925 if (NT_SUCCESS(Status))
926 {
927 if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
928 {
929 /* create the pin */
930 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
931
932 if (NT_SUCCESS(Status))
933 {
934 /* successfully created pin, increment pin instance count */
935 This->PinInstanceCount[Connect->PinId]++;
936 }
937 }
938 else
939 {
940 /* maximum instance count reached, bye-bye */
941 Status = STATUS_UNSUCCESSFUL;
942 }
943 }
944
945 /* release control mutex */
946 KeReleaseMutex(&This->Header.ControlMutex, FALSE);
947
948 if (Status != STATUS_PENDING)
949 {
950 /* complete request */
951 Irp->IoStatus.Status = Status;
952 IoCompleteRequest(Irp, IO_NO_INCREMENT);
953 }
954 /* done */
955 return Status;
956 }
957
958 NTSTATUS
959 NTAPI
960 IKsFilter_DispatchCreateNode(
961 IN PDEVICE_OBJECT DeviceObject,
962 IN PIRP Irp)
963 {
964 UNIMPLEMENTED
965 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
966 IoCompleteRequest(Irp, IO_NO_INCREMENT);
967 return STATUS_UNSUCCESSFUL;
968 }
969
970
971 NTSTATUS
972 NTAPI
973 KspCreateFilter(
974 IN PDEVICE_OBJECT DeviceObject,
975 IN PIRP Irp,
976 IN IKsFilterFactory *iface)
977 {
978 IKsFilterImpl * This;
979 IKsDevice *KsDevice;
980 PKSFILTERFACTORY Factory;
981 PIO_STACK_LOCATION IoStack;
982 PDEVICE_EXTENSION DeviceExtension;
983 NTSTATUS Status;
984 PKSOBJECT_CREATE_ITEM CreateItem;
985
986 /* get device extension */
987 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
988
989 /* get the filter factory */
990 Factory = iface->lpVtbl->GetStruct(iface);
991
992 if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
993 {
994 /* Sorry it just will not work */
995 return STATUS_UNSUCCESSFUL;
996 }
997
998 /* allocate filter instance */
999 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory));
1000 if (!This)
1001 return STATUS_INSUFFICIENT_RESOURCES;
1002
1003 /* copy filter descriptor */
1004 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1005 if (!NT_SUCCESS(Status))
1006 {
1007 /* not enough memory */
1008 FreeItem(This);
1009 return STATUS_INSUFFICIENT_RESOURCES;
1010 }
1011
1012 /* get current irp stack */
1013 IoStack = IoGetCurrentIrpStackLocation(Irp);
1014
1015 /* initialize object bag */
1016 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1017 if (!This->Filter.Bag)
1018 {
1019 /* no memory */
1020 FreeItem(This);
1021 return STATUS_INSUFFICIENT_RESOURCES;
1022 }
1023
1024 /* allocate create items */
1025 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1026 if (!CreateItem)
1027 {
1028 /* no memory */
1029 FreeItem(This);
1030 return STATUS_INSUFFICIENT_RESOURCES;
1031 }
1032
1033 /* initialize pin create item */
1034 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1035 CreateItem[0].Context = (PVOID)This;
1036 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1037 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1038 /* initialize node create item */
1039 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1040 CreateItem[1].Context = (PVOID)This;
1041 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1042 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1043
1044
1045 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1046 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1047
1048 /* initialize filter instance */
1049 This->ref = 1;
1050 This->lpVtbl = &vt_IKsFilter;
1051 This->lpVtblKsControl = &vt_IKsControl;
1052
1053 This->Filter.Descriptor = Factory->FilterDescriptor;
1054 This->Factory = Factory;
1055 This->FilterFactory = iface;
1056 This->FileObject = IoStack->FileObject;
1057 KeInitializeMutex(&This->ProcessingMutex, 0);
1058 /* initialize basic header */
1059 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1060 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1061 This->Header.Type = KsObjectTypeFilter;
1062 KeInitializeMutex(&This->Header.ControlMutex, 0);
1063 InitializeListHead(&This->Header.EventList);
1064 KeInitializeSpinLock(&This->Header.EventListLock);
1065
1066
1067
1068
1069
1070 /* allocate the stream descriptors */
1071 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1072 if (!NT_SUCCESS(Status))
1073 {
1074 /* what can go wrong, goes wrong */
1075 FreeItem(This);
1076 FreeItem(CreateItem);
1077 return Status;
1078 }
1079
1080 /* now add the filter instance to the filter factory */
1081 Status = iface->lpVtbl->AddFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
1082
1083 if (!NT_SUCCESS(Status))
1084 {
1085 /* failed to add filter */
1086 FreeItem(This);
1087 FreeItem(CreateItem);
1088 return Status;
1089 }
1090
1091 /* now let driver initialize the filter instance */
1092 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1093
1094 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1095 {
1096 /* driver failed to initialize */
1097 DPRINT1("Driver: Status %x\n", Status);
1098
1099 /* remove filter instance from filter factory */
1100 iface->lpVtbl->RemoveFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
1101
1102 /* free filter instance */
1103 FreeItem(This);
1104 FreeItem(CreateItem);
1105 return Status;
1106 }
1107
1108 /* now allocate the object header */
1109 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1110 if (!NT_SUCCESS(Status))
1111 {
1112 /* failed to allocate object header */
1113 DPRINT1("Failed to allocate object header %x\n", Status);
1114
1115 return Status;
1116 }
1117
1118 /* initialize object header extra fields */
1119 This->ObjectHeader->Type = KsObjectTypeFilter;
1120 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1121 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1122
1123
1124 /* completed initialization */
1125 return Status;
1126 }
1127
1128 /*
1129 @implemented
1130 */
1131 KSDDKAPI
1132 VOID
1133 NTAPI
1134 KsFilterAcquireProcessingMutex(
1135 IN PKSFILTER Filter)
1136 {
1137 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1138
1139 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1140 }
1141
1142 /*
1143 @implemented
1144 */
1145 KSDDKAPI
1146 VOID
1147 NTAPI
1148 KsFilterReleaseProcessingMutex(
1149 IN PKSFILTER Filter)
1150 {
1151 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1152
1153 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1154 }
1155
1156 /*
1157 @implemented
1158 */
1159 KSDDKAPI
1160 NTSTATUS
1161 NTAPI
1162 KsFilterAddTopologyConnections (
1163 IN PKSFILTER Filter,
1164 IN ULONG NewConnectionsCount,
1165 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1166 {
1167 ULONG Count;
1168 KSTOPOLOGY_CONNECTION * Connections;
1169 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1170
1171 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1172
1173 /* allocate array */
1174 Connections = AllocateItem(NonPagedPool, Count * sizeof(KSTOPOLOGY_CONNECTION));
1175 if (!Connections)
1176 return STATUS_INSUFFICIENT_RESOURCES;
1177
1178 /* FIXME verify connections */
1179
1180 if (This->Filter.Descriptor->ConnectionsCount)
1181 {
1182 /* copy old connections */
1183 RtlMoveMemory(Connections, This->Filter.Descriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * This->Filter.Descriptor->ConnectionsCount);
1184 }
1185
1186 /* add new connections */
1187 RtlMoveMemory((PVOID)(Connections + This->Filter.Descriptor->ConnectionsCount), NewTopologyConnections, NewConnectionsCount);
1188
1189 /* add the new connections */
1190 RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */
1191
1192 /* free old connections array */
1193 if (This->Filter.Descriptor->ConnectionsCount)
1194 {
1195 FreeItem((PVOID)This->Filter.Descriptor->Connections);
1196 }
1197
1198 /* brain-dead gcc hack */
1199 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*));
1200
1201 return STATUS_SUCCESS;
1202 }
1203
1204 /*
1205 @unimplemented
1206 */
1207 KSDDKAPI
1208 VOID
1209 NTAPI
1210 KsFilterAttemptProcessing(
1211 IN PKSFILTER Filter,
1212 IN BOOLEAN Asynchronous)
1213 {
1214 UNIMPLEMENTED
1215 }
1216
1217 /*
1218 @unimplemented
1219 */
1220 KSDDKAPI
1221 NTSTATUS
1222 NTAPI
1223 KsFilterCreateNode (
1224 IN PKSFILTER Filter,
1225 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1226 OUT PULONG NodeID)
1227 {
1228 UNIMPLEMENTED
1229 return STATUS_NOT_IMPLEMENTED;
1230 }
1231
1232 /*
1233 @implemented
1234 */
1235 KSDDKAPI
1236 NTSTATUS
1237 NTAPI
1238 KsFilterCreatePinFactory (
1239 IN PKSFILTER Filter,
1240 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1241 OUT PULONG PinID)
1242 {
1243 ULONG Count;
1244 ULONG *PinInstanceCount;
1245 KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
1246 KSPIN_DESCRIPTOR * PinDescriptors;
1247 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1248
1249 /* calculate existing count */
1250 Count = This->PinDescriptorCount + 1;
1251
1252 /* allocate pin descriptors array */
1253 PinDescriptorsEx = AllocateItem(NonPagedPool, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * Count);
1254 if (!PinDescriptorsEx)
1255 return STATUS_INSUFFICIENT_RESOURCES;
1256
1257 /* allocate pin instance count array */
1258 PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * Count);
1259 if (!PinInstanceCount)
1260 {
1261 /* not enough memory */
1262 FreeItem(PinDescriptorsEx);
1263 return STATUS_INSUFFICIENT_RESOURCES;
1264 }
1265
1266 /* allocate pin descriptor array for pin property handling */
1267 PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * Count);
1268 if (!PinDescriptors)
1269 {
1270 /* not enough memory */
1271 FreeItem(PinDescriptorsEx);
1272 FreeItem(PinInstanceCount);
1273 return STATUS_INSUFFICIENT_RESOURCES;
1274 }
1275
1276 /* now copy all fields */
1277 if (Count > 1)
1278 {
1279 /* copy old descriptors */
1280 RtlMoveMemory(PinDescriptorsEx, This->Filter.Descriptor->PinDescriptors, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount);
1281 RtlMoveMemory(PinInstanceCount, This->PinInstanceCount, This->PinDescriptorCount * sizeof(ULONG));
1282 RtlMoveMemory(PinDescriptors, This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * This->PinDescriptorCount);
1283
1284 /* now free old descriptors */
1285 FreeItem(This->PinInstanceCount);
1286 FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
1287 FreeItem(This->PinDescriptors);
1288 }
1289
1290 /* add new pin factory */
1291 RtlMoveMemory((PVOID)((ULONG_PTR)PinDescriptorsEx + max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount), InPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1292 RtlMoveMemory((PVOID)(PinDescriptors + This->PinDescriptorCount), &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1293
1294 /* replace old descriptor by using a gcc-compliant hack */
1295 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX*));
1296 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptorsCount, &Count, sizeof(ULONG));
1297
1298 This->PinDescriptors = PinDescriptors;
1299 This->PinInstanceCount = PinInstanceCount;
1300
1301 /* store new pin id */
1302 *PinID = This->PinDescriptorCount;
1303
1304 /* increment pin descriptor count */
1305 This->PinDescriptorCount++;
1306
1307 return STATUS_SUCCESS;
1308
1309 }
1310
1311 /*
1312 @unimplemented
1313 */
1314 KSDDKAPI
1315 PKSGATE
1316 NTAPI
1317 KsFilterGetAndGate(
1318 IN PKSFILTER Filter)
1319 {
1320 UNIMPLEMENTED
1321 return NULL;
1322 }
1323
1324 /*
1325 @implemented
1326 */
1327 KSDDKAPI
1328 ULONG
1329 NTAPI
1330 KsFilterGetChildPinCount(
1331 IN PKSFILTER Filter,
1332 IN ULONG PinId)
1333 {
1334 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1335
1336 if (PinId >= This->PinDescriptorCount)
1337 {
1338 /* index is out of bounds */
1339 return 0;
1340 }
1341 /* return pin instance count */
1342 return This->PinInstanceCount[PinId];
1343 }
1344
1345 /*
1346 @unimplemented
1347 */
1348 KSDDKAPI
1349 PKSPIN
1350 NTAPI
1351 KsFilterGetFirstChildPin(
1352 IN PKSFILTER Filter,
1353 IN ULONG PinId)
1354 {
1355 UNIMPLEMENTED
1356 return NULL;
1357 }
1358
1359 /*
1360 @implemented
1361 */
1362 KSDDKAPI
1363 VOID
1364 NTAPI
1365 KsFilterRegisterPowerCallbacks(
1366 IN PKSFILTER Filter,
1367 IN PFNKSFILTERPOWER Sleep OPTIONAL,
1368 IN PFNKSFILTERPOWER Wake OPTIONAL)
1369 {
1370 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1371
1372 This->Sleep = Sleep;
1373 This->Wake = Wake;
1374 }
1375
1376 /*
1377 @implemented
1378 */
1379 KSDDKAPI
1380 PKSFILTER
1381 NTAPI
1382 KsGetFilterFromIrp(
1383 IN PIRP Irp)
1384 {
1385 PIO_STACK_LOCATION IoStack;
1386 PKSIOBJECT_HEADER ObjectHeader;
1387
1388 /* get current irp stack location */
1389 IoStack = IoGetCurrentIrpStackLocation(Irp);
1390
1391 /* sanity check */
1392 ASSERT(IoStack->FileObject);
1393
1394 /* get object header */
1395 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
1396
1397 if (ObjectHeader->Type == KsObjectTypeFilter)
1398 {
1399 /* irp is targeted at the filter */
1400 return (PKSFILTER)ObjectHeader->ObjectType;
1401 }
1402 else if (ObjectHeader->Type == KsObjectTypePin)
1403 {
1404 /* irp is for a pin */
1405 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
1406 }
1407 else
1408 {
1409 /* irp is unappropiate to retrieve a filter */
1410 return NULL;
1411 }
1412 }