773302b233a3e24d4ed9464d12619da132d19345
[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 Irp->IoStatus.Status = Status;
750 IoCompleteRequest(Irp, IO_NO_INCREMENT);
751
752 /* done */
753 return Status;
754 }
755
756 static KSDISPATCH_TABLE DispatchTable =
757 {
758 IKsFilter_DispatchDeviceIoControl,
759 KsDispatchInvalidDeviceRequest,
760 KsDispatchInvalidDeviceRequest,
761 KsDispatchInvalidDeviceRequest,
762 IKsFilter_DispatchClose,
763 KsDispatchQuerySecurity,
764 KsDispatchSetSecurity,
765 KsDispatchFastIoDeviceControlFailure,
766 KsDispatchFastReadFailure,
767 KsDispatchFastReadFailure,
768 };
769
770
771 NTSTATUS
772 IKsFilter_CreateDescriptors(
773 IKsFilterImpl * This,
774 KSFILTER_DESCRIPTOR* FilterDescriptor)
775 {
776 ULONG Index = 0;
777 NTSTATUS Status;
778
779 /* initialize pin descriptors */
780 This->FirstPin = NULL;
781 This->PinInstanceCount = NULL;
782 This->PinDescriptors = NULL;
783 This->PinDescriptorsEx = NULL;
784 This->PinDescriptorCount = 0;
785
786 /* initialize topology descriptor */
787 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
788 This->Topology.Categories = FilterDescriptor->Categories;
789 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
790 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
791 This->Topology.TopologyConnections = FilterDescriptor->Connections;
792
793 /* are there any templates */
794 if (FilterDescriptor->PinDescriptorsCount)
795 {
796 /* sanity check */
797 ASSERT(FilterDescriptor->PinDescriptors);
798
799 /* FIXME handle variable sized pin descriptors */
800 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
801
802 /* store pin descriptors ex */
803 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount,
804 sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, 0);
805
806 if (!NT_SUCCESS(Status))
807 {
808 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
809 return Status;
810 }
811
812 /* store pin descriptors */
813 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount,
814 sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, 0);
815
816 if (!NT_SUCCESS(Status))
817 {
818 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
819 return Status;
820 }
821
822 /* store pin instance count ex */
823 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
824 sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
825
826 if (!NT_SUCCESS(Status))
827 {
828 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
829 return Status;
830 }
831
832 /* store instantiated pin arrays */
833 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
834 sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
835
836 if (!NT_SUCCESS(Status))
837 {
838 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
839 return Status;
840 }
841
842
843
844 /* add new pin factory */
845 RtlMoveMemory(This->PinDescriptorsEx, FilterDescriptor->PinDescriptors, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount);
846
847 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
848 {
849 RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
850 }
851
852 /* store new pin descriptor count */
853 This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
854 }
855
856 if (FilterDescriptor->NodeDescriptorsCount)
857 {
858 /* sanity check */
859 ASSERT(FilterDescriptor->NodeDescriptors);
860
861 /* FIXME handle variable sized node descriptors */
862 ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
863
864 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
865 /* allocate topology node types array */
866 if (!This->Topology.TopologyNodes)
867 {
868 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
869 return STATUS_INSUFFICIENT_RESOURCES;
870 }
871
872 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
873 /* allocate topology names array */
874 if (!This->Topology.TopologyNodesNames)
875 {
876 FreeItem((PVOID)This->Topology.TopologyNodes);
877 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
878 return STATUS_INSUFFICIENT_RESOURCES;
879 }
880
881 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
882 for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
883 {
884 DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
885
886 /* copy topology type */
887 if (FilterDescriptor->NodeDescriptors[Index].Type)
888 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
889
890 /* copy topology name */
891 if (FilterDescriptor->NodeDescriptors[Index].Name)
892 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
893 }
894 }
895 /* done! */
896 return STATUS_SUCCESS;
897 }
898
899 NTSTATUS
900 IKsFilter_CopyFilterDescriptor(
901 IKsFilterImpl * This,
902 const KSFILTER_DESCRIPTOR* FilterDescriptor)
903 {
904 NTSTATUS Status;
905
906 This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
907 if (!This->Filter.Descriptor)
908 return STATUS_INSUFFICIENT_RESOURCES;
909
910 Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
911 if (!NT_SUCCESS(Status))
912 {
913 FreeItem((PVOID)This->Filter.Descriptor);
914 This->Filter.Descriptor = NULL;
915 return STATUS_INSUFFICIENT_RESOURCES;
916 }
917
918 /* copy filter descriptor fields */
919 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
920
921 return Status;
922 }
923
924
925 NTSTATUS
926 IKsFilter_AddPin(
927 IKsFilter * Filter,
928 PKSPIN Pin)
929 {
930 PKSPIN NextPin, CurPin;
931 PKSBASIC_HEADER BasicHeader;
932 IKsFilterImpl * This = (IKsFilterImpl*)Filter;
933
934 /* sanity check */
935 ASSERT(Pin->Id < This->PinDescriptorCount);
936
937 if (This->FirstPin[Pin->Id] == NULL)
938 {
939 /* welcome first pin */
940 This->FirstPin[Pin->Id] = Pin;
941 return STATUS_SUCCESS;
942 }
943
944 /* get first pin */
945 CurPin = This->FirstPin[Pin->Id];
946
947 do
948 {
949 /* get next instantiated pin */
950 NextPin = KsPinGetNextSiblingPin(CurPin);
951 if (!NextPin)
952 break;
953
954 NextPin = CurPin;
955
956 }while(NextPin != NULL);
957
958 /* get basic header */
959 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
960
961 /* store pin */
962 BasicHeader->Next.Pin = Pin;
963
964 return STATUS_SUCCESS;
965 }
966
967
968 NTSTATUS
969 NTAPI
970 IKsFilter_DispatchCreatePin(
971 IN PDEVICE_OBJECT DeviceObject,
972 IN PIRP Irp)
973 {
974 IKsFilterImpl * This;
975 PKSOBJECT_CREATE_ITEM CreateItem;
976 PKSPIN_CONNECT Connect;
977 NTSTATUS Status;
978
979 DPRINT("IKsFilter_DispatchCreatePin\n");
980
981 /* get the create item */
982 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
983
984 /* get the filter object */
985 This = (IKsFilterImpl*)CreateItem->Context;
986
987 /* sanity check */
988 ASSERT(This->Header.Type == KsObjectTypeFilter);
989
990 /* acquire control mutex */
991 KeWaitForSingleObject(&This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
992
993 /* now validate the connect request */
994 Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect);
995
996 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
997
998 if (NT_SUCCESS(Status))
999 {
1000 /* sanity check */
1001 ASSERT(Connect->PinId < This->PinDescriptorCount);
1002
1003 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1004 This->PinInstanceCount[Connect->PinId],
1005 This->PinDescriptorsEx[Connect->PinId].InstancesPossible);
1006
1007 if (This->PinInstanceCount[Connect->PinId] < This->PinDescriptorsEx[Connect->PinId].InstancesPossible)
1008 {
1009 /* create the pin */
1010 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[Connect->PinId]);
1011
1012 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status);
1013
1014 if (NT_SUCCESS(Status))
1015 {
1016 /* successfully created pin, increment pin instance count */
1017 This->PinInstanceCount[Connect->PinId]++;
1018 }
1019 }
1020 else
1021 {
1022 /* maximum instance count reached, bye-bye */
1023 Status = STATUS_UNSUCCESSFUL;
1024 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->PinDescriptorsEx[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1025 }
1026 }
1027
1028 /* release control mutex */
1029 KeReleaseMutex(&This->Header.ControlMutex, FALSE);
1030
1031 if (Status != STATUS_PENDING)
1032 {
1033 /* complete request */
1034 Irp->IoStatus.Status = Status;
1035 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1036 }
1037
1038 /* done */
1039 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1040 return Status;
1041 }
1042
1043 NTSTATUS
1044 NTAPI
1045 IKsFilter_DispatchCreateNode(
1046 IN PDEVICE_OBJECT DeviceObject,
1047 IN PIRP Irp)
1048 {
1049 UNIMPLEMENTED
1050 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1051 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1052 return STATUS_UNSUCCESSFUL;
1053 }
1054
1055
1056 VOID
1057 IKsFilter_AttachFilterToFilterFactory(
1058 IKsFilterImpl * This,
1059 PKSFILTERFACTORY FilterFactory)
1060 {
1061 PKSBASIC_HEADER BasicHeader;
1062 PKSFILTER Filter;
1063
1064
1065 /* get filter factory basic header */
1066 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1067
1068 /* sanity check */
1069 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1070
1071 if (BasicHeader->FirstChild.FilterFactory == NULL)
1072 {
1073 /* welcome first instantiated filter */
1074 BasicHeader->FirstChild.Filter = &This->Filter;
1075 return;
1076 }
1077
1078 /* set to first entry */
1079 Filter = BasicHeader->FirstChild.Filter;
1080
1081 do
1082 {
1083 /* get basic header */
1084 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1085 /* sanity check */
1086 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1087
1088 if (BasicHeader->Next.Filter)
1089 {
1090 /* iterate to next filter factory */
1091 Filter = BasicHeader->Next.Filter;
1092 }
1093 else
1094 {
1095 /* found last entry */
1096 break;
1097 }
1098 }while(FilterFactory);
1099
1100 /* attach filter factory */
1101 BasicHeader->Next.Filter = &This->Filter;
1102 }
1103
1104 NTSTATUS
1105 NTAPI
1106 KspCreateFilter(
1107 IN PDEVICE_OBJECT DeviceObject,
1108 IN PIRP Irp,
1109 IN IKsFilterFactory *iface)
1110 {
1111 IKsFilterImpl * This;
1112 IKsDevice *KsDevice;
1113 PKSFILTERFACTORY Factory;
1114 PIO_STACK_LOCATION IoStack;
1115 PDEVICE_EXTENSION DeviceExtension;
1116 NTSTATUS Status;
1117 PKSOBJECT_CREATE_ITEM CreateItem;
1118
1119 /* get device extension */
1120 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1121
1122 /* get the filter factory */
1123 Factory = iface->lpVtbl->GetStruct(iface);
1124
1125 if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
1126 {
1127 /* Sorry it just will not work */
1128 return STATUS_UNSUCCESSFUL;
1129 }
1130
1131 /* allocate filter instance */
1132 This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1133 if (!This)
1134 {
1135 DPRINT("KspCreateFilter OutOfMemory\n");
1136 return STATUS_INSUFFICIENT_RESOURCES;
1137 }
1138
1139 /* initialize object bag */
1140 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1141 if (!This->Filter.Bag)
1142 {
1143 /* no memory */
1144 FreeItem(This);
1145 DPRINT("KspCreateFilter OutOfMemory\n");
1146 return STATUS_INSUFFICIENT_RESOURCES;
1147 }
1148 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1149 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1150
1151 /* copy filter descriptor */
1152 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 /* not enough memory */
1156 FreeItem(This->Filter.Bag);
1157 FreeItem(This);
1158 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1159 return STATUS_INSUFFICIENT_RESOURCES;
1160 }
1161
1162 /* get current irp stack */
1163 IoStack = IoGetCurrentIrpStackLocation(Irp);
1164
1165 /* allocate create items */
1166 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1167 if (!CreateItem)
1168 {
1169 /* no memory */
1170 FreeItem(This->Filter.Bag);
1171 FreeItem(This);
1172 DPRINT("KspCreateFilter OutOfMemory\n");
1173 return STATUS_INSUFFICIENT_RESOURCES;
1174 }
1175
1176 /* initialize pin create item */
1177 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1178 CreateItem[0].Context = (PVOID)This;
1179 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1180 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1181 /* initialize node create item */
1182 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1183 CreateItem[1].Context = (PVOID)This;
1184 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1185 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1186
1187
1188 /* initialize filter instance */
1189 This->ref = 1;
1190 This->lpVtbl = &vt_IKsFilter;
1191 This->lpVtblKsControl = &vt_IKsControl;
1192
1193 This->Filter.Descriptor = Factory->FilterDescriptor;
1194 This->Factory = Factory;
1195 This->FilterFactory = iface;
1196 This->FileObject = IoStack->FileObject;
1197 KeInitializeMutex(&This->ProcessingMutex, 0);
1198 /* initialize basic header */
1199 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1200 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1201 This->Header.Type = KsObjectTypeFilter;
1202 KeInitializeMutex(&This->Header.ControlMutex, 0);
1203 InitializeListHead(&This->Header.EventList);
1204 KeInitializeSpinLock(&This->Header.EventListLock);
1205
1206 /* allocate the stream descriptors */
1207 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1208 if (!NT_SUCCESS(Status))
1209 {
1210 /* what can go wrong, goes wrong */
1211 FreeItem(This);
1212 FreeItem(CreateItem);
1213 DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1214 return Status;
1215 }
1216
1217 /* does the filter have a filter dispatch */
1218 if (Factory->FilterDescriptor->Dispatch)
1219 {
1220 /* does it have a create routine */
1221 if (Factory->FilterDescriptor->Dispatch->Create)
1222 {
1223 /* now let driver initialize the filter instance */
1224 DPRINT("Before instantiating filter Filter %p This %p KSBASIC_HEADER %u\n", &This->Filter, This, sizeof(KSBASIC_HEADER));
1225 ASSERT(This->Header.KsDevice);
1226 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1227
1228 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1229 {
1230 /* driver failed to initialize */
1231 DPRINT1("Driver: Status %x\n", Status);
1232
1233 /* free filter instance */
1234 FreeItem(This);
1235 FreeItem(CreateItem);
1236 return Status;
1237 }
1238 }
1239 }
1240
1241 /* now allocate the object header */
1242 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1243 if (!NT_SUCCESS(Status))
1244 {
1245 /* failed to allocate object header */
1246 DPRINT1("Failed to allocate object header %x\n", Status);
1247
1248 return Status;
1249 }
1250
1251 /* initialize object header extra fields */
1252 This->ObjectHeader->Type = KsObjectTypeFilter;
1253 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1254 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1255
1256 /* attach filter to filter factory */
1257 IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1258
1259 /* completed initialization */
1260 DPRINT("KspCreateFilter done %lx\n", Status);
1261 return Status;
1262 }
1263
1264 /*
1265 @implemented
1266 */
1267 KSDDKAPI
1268 VOID
1269 NTAPI
1270 KsFilterAcquireProcessingMutex(
1271 IN PKSFILTER Filter)
1272 {
1273 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1274
1275 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1276 }
1277
1278 /*
1279 @implemented
1280 */
1281 KSDDKAPI
1282 VOID
1283 NTAPI
1284 KsFilterReleaseProcessingMutex(
1285 IN PKSFILTER Filter)
1286 {
1287 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1288
1289 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1290 }
1291
1292 /*
1293 @implemented
1294 */
1295 KSDDKAPI
1296 NTSTATUS
1297 NTAPI
1298 KsFilterAddTopologyConnections (
1299 IN PKSFILTER Filter,
1300 IN ULONG NewConnectionsCount,
1301 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1302 {
1303 ULONG Count;
1304 KSTOPOLOGY_CONNECTION * Connections;
1305 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1306
1307 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1308
1309 /* allocate array */
1310 Connections = AllocateItem(NonPagedPool, Count * sizeof(KSTOPOLOGY_CONNECTION));
1311 if (!Connections)
1312 return STATUS_INSUFFICIENT_RESOURCES;
1313
1314 /* FIXME verify connections */
1315
1316 if (This->Filter.Descriptor->ConnectionsCount)
1317 {
1318 /* copy old connections */
1319 RtlMoveMemory(Connections, This->Filter.Descriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * This->Filter.Descriptor->ConnectionsCount);
1320 }
1321
1322 /* add new connections */
1323 RtlMoveMemory((PVOID)(Connections + This->Filter.Descriptor->ConnectionsCount), NewTopologyConnections, NewConnectionsCount);
1324
1325 /* add the new connections */
1326 RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */
1327
1328 /* free old connections array */
1329 if (This->Filter.Descriptor->ConnectionsCount)
1330 {
1331 FreeItem((PVOID)This->Filter.Descriptor->Connections);
1332 }
1333
1334 /* brain-dead gcc hack */
1335 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*));
1336
1337 return STATUS_SUCCESS;
1338 }
1339
1340 /*
1341 @unimplemented
1342 */
1343 KSDDKAPI
1344 VOID
1345 NTAPI
1346 KsFilterAttemptProcessing(
1347 IN PKSFILTER Filter,
1348 IN BOOLEAN Asynchronous)
1349 {
1350 UNIMPLEMENTED
1351 }
1352
1353 /*
1354 @unimplemented
1355 */
1356 KSDDKAPI
1357 NTSTATUS
1358 NTAPI
1359 KsFilterCreateNode (
1360 IN PKSFILTER Filter,
1361 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1362 OUT PULONG NodeID)
1363 {
1364 UNIMPLEMENTED
1365 return STATUS_NOT_IMPLEMENTED;
1366 }
1367
1368 /*
1369 @implemented
1370 */
1371 KSDDKAPI
1372 NTSTATUS
1373 NTAPI
1374 KsFilterCreatePinFactory (
1375 IN PKSFILTER Filter,
1376 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1377 OUT PULONG PinID)
1378 {
1379 ULONG Count;
1380 NTSTATUS Status;
1381 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1382
1383 DPRINT("KsFilterCreatePinFactory\n");
1384
1385 /* calculate new count */
1386 Count = This->PinDescriptorCount + 1;
1387
1388 /* sanity check */
1389 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1390
1391 /* allocate pin descriptors ex array */
1392 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, Count * sizeof(KSPIN_DESCRIPTOR_EX), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR_EX), 0);
1393 if (!NT_SUCCESS(Status))
1394 {
1395 /* failed */
1396 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1397 return Status;
1398 }
1399
1400 /* allocate pin descriptors array */
1401 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR), 0);
1402 if (!NT_SUCCESS(Status))
1403 {
1404 /* failed */
1405 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1406 return Status;
1407 }
1408
1409
1410 /* allocate pin instance count array */
1411 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->PinDescriptorCount, 0);
1412 if (!NT_SUCCESS(Status))
1413 {
1414 /* failed */
1415 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1416 return Status;
1417 }
1418
1419 /* allocate first pin array */
1420 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->PinDescriptorCount, 0);
1421 if (!NT_SUCCESS(Status))
1422 {
1423 /* failed */
1424 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1425 return Status;
1426 }
1427
1428 /* add new pin factory */
1429 RtlMoveMemory(&This->PinDescriptorsEx[This->PinDescriptorCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
1430 RtlMoveMemory(&This->PinDescriptors[This->PinDescriptorCount], &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
1431
1432 /* store new pin id */
1433 *PinID = This->PinDescriptorCount;
1434
1435 /* increment pin descriptor count */
1436 This->PinDescriptorCount++;
1437
1438
1439 DPRINT("KsFilterCreatePinFactory done\n");
1440 return STATUS_SUCCESS;
1441
1442 }
1443
1444 /*
1445 @unimplemented
1446 */
1447 KSDDKAPI
1448 PKSGATE
1449 NTAPI
1450 KsFilterGetAndGate(
1451 IN PKSFILTER Filter)
1452 {
1453 UNIMPLEMENTED
1454 return NULL;
1455 }
1456
1457 /*
1458 @implemented
1459 */
1460 KSDDKAPI
1461 ULONG
1462 NTAPI
1463 KsFilterGetChildPinCount(
1464 IN PKSFILTER Filter,
1465 IN ULONG PinId)
1466 {
1467 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1468
1469 if (PinId >= This->PinDescriptorCount)
1470 {
1471 /* index is out of bounds */
1472 return 0;
1473 }
1474 /* return pin instance count */
1475 return This->PinInstanceCount[PinId];
1476 }
1477
1478 /*
1479 @implemented
1480 */
1481 KSDDKAPI
1482 PKSPIN
1483 NTAPI
1484 KsFilterGetFirstChildPin(
1485 IN PKSFILTER Filter,
1486 IN ULONG PinId)
1487 {
1488 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1489
1490 if (PinId >= This->PinDescriptorCount)
1491 {
1492 /* index is out of bounds */
1493 return NULL;
1494 }
1495
1496 /* return first pin index */
1497 return This->FirstPin[PinId];
1498 }
1499
1500 /*
1501 @implemented
1502 */
1503 KSDDKAPI
1504 VOID
1505 NTAPI
1506 KsFilterRegisterPowerCallbacks(
1507 IN PKSFILTER Filter,
1508 IN PFNKSFILTERPOWER Sleep OPTIONAL,
1509 IN PFNKSFILTERPOWER Wake OPTIONAL)
1510 {
1511 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1512
1513 This->Sleep = Sleep;
1514 This->Wake = Wake;
1515 }
1516
1517 /*
1518 @implemented
1519 */
1520 KSDDKAPI
1521 PKSFILTER
1522 NTAPI
1523 KsGetFilterFromIrp(
1524 IN PIRP Irp)
1525 {
1526 PIO_STACK_LOCATION IoStack;
1527 PKSIOBJECT_HEADER ObjectHeader;
1528
1529 /* get current irp stack location */
1530 IoStack = IoGetCurrentIrpStackLocation(Irp);
1531
1532 /* sanity check */
1533 ASSERT(IoStack->FileObject);
1534
1535 /* get object header */
1536 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1537
1538 if (ObjectHeader->Type == KsObjectTypeFilter)
1539 {
1540 /* irp is targeted at the filter */
1541 return (PKSFILTER)ObjectHeader->ObjectType;
1542 }
1543 else if (ObjectHeader->Type == KsObjectTypePin)
1544 {
1545 /* irp is for a pin */
1546 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
1547 }
1548 else
1549 {
1550 /* irp is unappropiate to retrieve a filter */
1551 return NULL;
1552 }
1553 }