[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / pin.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/worker.c
5 * PURPOSE: KS pin functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 typedef struct _KSISTREAM_POINTER
13 {
14 KSSTREAM_POINTER StreamPointer;
15 PFNKSSTREAMPOINTER Callback;
16 PIRP Irp;
17 KTIMER Timer;
18 KDPC TimerDpc;
19 struct _KSISTREAM_POINTER *Next;
20
21 }KSISTREAM_POINTER, *PKSISTREAM_POINTER;
22
23 typedef struct
24 {
25 KSBASIC_HEADER BasicHeader;
26 KSPIN Pin;
27 PKSIOBJECT_HEADER ObjectHeader;
28 KSPROCESSPIN ProcessPin;
29 LIST_ENTRY Entry;
30
31 IKsPinVtbl *lpVtbl;
32
33 LONG ref;
34 KMUTEX ProcessingMutex;
35 PFILE_OBJECT FileObject;
36
37 PKSGATE AttachedGate;
38 BOOL OrGate;
39
40 LIST_ENTRY IrpList;
41 KSPIN_LOCK IrpListLock;
42
43 PKSISTREAM_POINTER ClonedStreamPointer;
44 PKSISTREAM_POINTER LeadingEdgeStreamPointer;
45 PKSISTREAM_POINTER TrailingStreamPointer;
46
47 PFNKSPINPOWER Sleep;
48 PFNKSPINPOWER Wake;
49 PFNKSPINHANDSHAKE Handshake;
50 PFNKSPINFRAMERETURN FrameReturn;
51 PFNKSPINIRPCOMPLETION IrpCompletion;
52
53 }IKsPinImpl;
54
55 NTSTATUS
56 NTAPI
57 IKsPin_fnQueryInterface(
58 IKsPin * iface,
59 IN REFIID refiid,
60 OUT PVOID* Output)
61 {
62 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
63
64 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
65 {
66 *Output = &This->lpVtbl;
67 _InterlockedIncrement(&This->ref);
68 return STATUS_SUCCESS;
69 }
70 return STATUS_UNSUCCESSFUL;
71 }
72
73 ULONG
74 NTAPI
75 IKsPin_fnAddRef(
76 IKsPin * iface)
77 {
78 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
79
80 return InterlockedIncrement(&This->ref);
81 }
82
83 ULONG
84 NTAPI
85 IKsPin_fnRelease(
86 IKsPin * iface)
87 {
88 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
89
90 InterlockedDecrement(&This->ref);
91
92 if (This->ref == 0)
93 {
94 FreeItem(This);
95 return 0;
96 }
97 /* Return new reference count */
98 return This->ref;
99 }
100
101 NTSTATUS
102 NTAPI
103 IKsPin_fnTransferKsIrp(
104 IN IKsPin *iface,
105 IN PIRP Irp,
106 IN IKsTransport **OutTransport)
107 {
108 UNIMPLEMENTED
109 return STATUS_NOT_IMPLEMENTED;
110 }
111
112 VOID
113 NTAPI
114 IKsPin_fnDiscardKsIrp(
115 IN IKsPin *iface,
116 IN PIRP Irp,
117 IN IKsTransport * *OutTransport)
118 {
119 UNIMPLEMENTED
120 }
121
122
123 NTSTATUS
124 NTAPI
125 IKsPin_fnConnect(
126 IN IKsPin *iface,
127 IN IKsTransport * TransportIn,
128 OUT IKsTransport ** OutTransportIn,
129 OUT IKsTransport * *OutTransportOut,
130 IN KSPIN_DATAFLOW DataFlow)
131 {
132 UNIMPLEMENTED
133 return STATUS_NOT_IMPLEMENTED;
134 }
135
136 NTSTATUS
137 NTAPI
138 IKsPin_fnSetDeviceState(
139 IN IKsPin *iface,
140 IN KSSTATE OldState,
141 IN KSSTATE NewState,
142 IN IKsTransport * *OutTransport)
143 {
144 UNIMPLEMENTED
145 return STATUS_NOT_IMPLEMENTED;
146 }
147
148 VOID
149 NTAPI
150 IKsPin_fnSetResetState(
151 IN IKsPin *iface,
152 IN KSRESET ResetState,
153 OUT IKsTransport * * OutTransportOut)
154 {
155 UNIMPLEMENTED
156 }
157
158 NTSTATUS
159 NTAPI
160 IKsPin_fnGetTransportConfig(
161 IN IKsPin *iface,
162 IN struct KSPTRANSPORTCONFIG * TransportConfig,
163 OUT IKsTransport ** OutTransportIn,
164 OUT IKsTransport ** OutTransportOut)
165 {
166 UNIMPLEMENTED
167 return STATUS_NOT_IMPLEMENTED;
168 }
169
170 NTSTATUS
171 NTAPI
172 IKsPin_fnSetTransportConfig(
173 IN IKsPin *iface,
174 IN struct KSPTRANSPORTCONFIG const * TransportConfig,
175 OUT IKsTransport ** OutTransportIn,
176 OUT IKsTransport ** OutTransportOut)
177 {
178 UNIMPLEMENTED
179 return STATUS_NOT_IMPLEMENTED;
180 }
181
182 NTSTATUS
183 NTAPI
184 IKsPin_fnResetTransportConfig(
185 IN IKsPin *iface,
186 OUT IKsTransport ** OutTransportIn,
187 OUT IKsTransport ** OutTransportOut)
188 {
189 UNIMPLEMENTED
190 return STATUS_NOT_IMPLEMENTED;
191 }
192
193 PKSPIN
194 NTAPI
195 IKsPin_fnGetStruct(
196 IN IKsPin *iface)
197 {
198 UNIMPLEMENTED
199 return NULL;
200 }
201
202 PKSPROCESSPIN
203 NTAPI
204 IKsPin_fnGetProcessPin(
205 IN IKsPin *iface)
206 {
207 UNIMPLEMENTED
208 return NULL;
209 }
210
211 NTSTATUS
212 NTAPI
213 IKsPin_fnAttemptBypass(
214 IN IKsPin *iface)
215 {
216 UNIMPLEMENTED
217 return STATUS_NOT_IMPLEMENTED;
218 }
219
220 NTSTATUS
221 NTAPI
222 IKsPin_fnAttemptUnbypass(
223 IN IKsPin *iface)
224 {
225 UNIMPLEMENTED
226 return STATUS_NOT_IMPLEMENTED;
227 }
228
229 VOID
230 NTAPI
231 IKsPin_fnGenerateConnectionEvents(
232 IN IKsPin *iface,
233 IN ULONG EventMask)
234 {
235 UNIMPLEMENTED
236 }
237
238 NTSTATUS
239 NTAPI
240 IKsPin_fnClientSetDeviceState(
241 IN IKsPin *iface,
242 IN KSSTATE StateIn,
243 IN KSSTATE StateOut)
244 {
245 UNIMPLEMENTED
246 return STATUS_NOT_IMPLEMENTED;
247 }
248
249 static IKsPinVtbl vt_IKsPin =
250 {
251 IKsPin_fnQueryInterface,
252 IKsPin_fnAddRef,
253 IKsPin_fnRelease,
254 IKsPin_fnTransferKsIrp,
255 IKsPin_fnDiscardKsIrp,
256 IKsPin_fnConnect,
257 IKsPin_fnSetDeviceState,
258 IKsPin_fnSetResetState,
259 IKsPin_fnGetTransportConfig,
260 IKsPin_fnSetTransportConfig,
261 IKsPin_fnResetTransportConfig,
262 IKsPin_fnGetStruct,
263 IKsPin_fnGetProcessPin,
264 IKsPin_fnAttemptBypass,
265 IKsPin_fnAttemptUnbypass,
266 IKsPin_fnGenerateConnectionEvents,
267 IKsPin_fnClientSetDeviceState
268 };
269
270
271 //==============================================================
272
273 /*
274 @implemented
275 */
276 VOID
277 NTAPI
278 KsPinAcquireProcessingMutex(
279 IN PKSPIN Pin)
280 {
281 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
282
283 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
284 }
285
286 /*
287 @implemented
288 */
289 VOID
290 NTAPI
291 KsPinAttachAndGate(
292 IN PKSPIN Pin,
293 IN PKSGATE AndGate OPTIONAL)
294 {
295 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
296
297 /* FIXME attach to filter's and gate (filter-centric processing) */
298
299 This->AttachedGate = AndGate;
300 This->OrGate = FALSE;
301 }
302
303 /*
304 @implemented
305 */
306 VOID
307 NTAPI
308 KsPinAttachOrGate(
309 IN PKSPIN Pin,
310 IN PKSGATE OrGate OPTIONAL)
311 {
312 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
313
314 /* FIXME attach to filter's and gate (filter-centric processing) */
315
316 This->AttachedGate = OrGate;
317 This->OrGate = TRUE;
318 }
319
320 /*
321 @implemented
322 */
323 PKSGATE
324 NTAPI
325 KsPinGetAndGate(
326 IN PKSPIN Pin)
327 {
328 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
329
330 return This->AttachedGate;
331 }
332
333 /*
334 @unimplemented
335 */
336 VOID
337 NTAPI
338 KsPinAttemptProcessing(
339 IN PKSPIN Pin,
340 IN BOOLEAN Asynchronous)
341 {
342 DPRINT("KsPinAttemptProcessing\n");
343 UNIMPLEMENTED
344 }
345
346 /*
347 @unimplemented
348 */
349 NTSTATUS
350 NTAPI
351 KsPinGetAvailableByteCount(
352 IN PKSPIN Pin,
353 OUT PLONG InputDataBytes OPTIONAL,
354 OUT PLONG OutputBufferBytes OPTIONAL)
355 {
356 UNIMPLEMENTED
357 return STATUS_NOT_IMPLEMENTED;
358 }
359
360 /*
361 @unimplemented
362 */
363 NTSTATUS
364 NTAPI
365 KsPinGetConnectedFilterInterface(
366 IN PKSPIN Pin,
367 IN const GUID* InterfaceId,
368 OUT PVOID* Interface)
369 {
370 UNIMPLEMENTED
371 return STATUS_NOT_IMPLEMENTED;
372 }
373
374 /*
375 @unimplemented
376 */
377 PDEVICE_OBJECT
378 NTAPI
379 KsPinGetConnectedPinDeviceObject(
380 IN PKSPIN Pin)
381 {
382 UNIMPLEMENTED
383 return NULL;
384 }
385
386 /*
387 @unimplemented
388 */
389 PFILE_OBJECT
390 NTAPI
391 KsPinGetConnectedPinFileObject(
392 IN PKSPIN Pin)
393 {
394 UNIMPLEMENTED
395 return NULL;
396 }
397
398 /*
399 @unimplemented
400 */
401 NTSTATUS
402 NTAPI
403 KsPinGetConnectedPinInterface(
404 IN PKSPIN Pin,
405 IN const GUID* InterfaceId,
406 OUT PVOID* Interface)
407 {
408 UNIMPLEMENTED
409 return STATUS_NOT_IMPLEMENTED;
410 }
411
412 /*
413 @unimplemented
414 */
415 VOID
416 NTAPI
417 KsPinGetCopyRelationships(
418 IN PKSPIN Pin,
419 OUT PKSPIN* CopySource,
420 OUT PKSPIN* DelegateBranch)
421 {
422 UNIMPLEMENTED
423 }
424
425 /*
426 @implemented
427 */
428 PKSPIN
429 NTAPI
430 KsPinGetNextSiblingPin(
431 IN PKSPIN Pin)
432 {
433 return KsGetNextSibling((PVOID)Pin);
434 }
435
436 /*
437 @implemented
438 */
439 PKSFILTER
440 NTAPI
441 KsPinGetParentFilter(
442 IN PKSPIN Pin)
443 {
444 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
445
446 /* return parent filter */
447 return This->BasicHeader.Parent.KsFilter;
448 }
449
450 /*
451 @unimplemented
452 */
453 NTSTATUS
454 NTAPI
455 KsPinGetReferenceClockInterface(
456 IN PKSPIN Pin,
457 OUT PIKSREFERENCECLOCK* Interface)
458 {
459 UNIMPLEMENTED
460 DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p\n", Pin, Interface);
461 return STATUS_UNSUCCESSFUL;
462 }
463
464 /*
465 @implemented
466 */
467 VOID
468 NTAPI
469 KsPinRegisterFrameReturnCallback(
470 IN PKSPIN Pin,
471 IN PFNKSPINFRAMERETURN FrameReturn)
472 {
473 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
474
475 /* register frame return callback */
476 This->FrameReturn = FrameReturn;
477 }
478
479 /*
480 @implemented
481 */
482 VOID
483 NTAPI
484 KsPinRegisterHandshakeCallback(
485 IN PKSPIN Pin,
486 IN PFNKSPINHANDSHAKE Handshake)
487 {
488 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
489
490 /* register private protocol handshake callback */
491 This->Handshake = Handshake;
492 }
493
494 /*
495 @implemented
496 */
497 VOID
498 NTAPI
499 KsPinRegisterIrpCompletionCallback(
500 IN PKSPIN Pin,
501 IN PFNKSPINIRPCOMPLETION IrpCompletion)
502 {
503 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
504
505 /* register irp completion callback */
506 This->IrpCompletion = IrpCompletion;
507 }
508
509 /*
510 @implemented
511 */
512 VOID
513 NTAPI
514 KsPinRegisterPowerCallbacks(
515 IN PKSPIN Pin,
516 IN PFNKSPINPOWER Sleep OPTIONAL,
517 IN PFNKSPINPOWER Wake OPTIONAL)
518 {
519 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
520
521 /* register power callbacks */
522 This->Sleep = Sleep;
523 This->Wake = Wake;
524 }
525
526 /*
527 @implemented
528 */
529 VOID
530 NTAPI
531 KsPinReleaseProcessingMutex(
532 IN PKSPIN Pin)
533 {
534 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
535
536 /* release processing mutex */
537 KeReleaseMutex(&This->ProcessingMutex, FALSE);
538 }
539
540 /*
541 @implemented
542 */
543 KSDDKAPI
544 PKSPIN
545 NTAPI
546 KsGetPinFromIrp(
547 IN PIRP Irp)
548 {
549 PKSIOBJECT_HEADER ObjectHeader;
550 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
551
552 DPRINT("KsGetPinFromIrp\n");
553
554 /* get object header */
555 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
556 /* return object type */
557 return (PKSPIN)ObjectHeader->ObjectType;
558
559 }
560
561
562
563 /*
564 @unimplemented
565 */
566 VOID
567 NTAPI
568 KsPinSetPinClockTime(
569 IN PKSPIN Pin,
570 IN LONGLONG Time)
571 {
572 UNIMPLEMENTED
573 }
574
575 /*
576 @unimplemented
577 */
578 NTSTATUS
579 NTAPI
580 KsPinSubmitFrame(
581 IN PKSPIN Pin,
582 IN PVOID Data OPTIONAL,
583 IN ULONG Size OPTIONAL,
584 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
585 IN PVOID Context OPTIONAL)
586 {
587 UNIMPLEMENTED
588 return STATUS_UNSUCCESSFUL;
589 }
590
591 /*
592 @unimplemented
593 */
594 KSDDKAPI
595 NTSTATUS
596 NTAPI
597 KsPinSubmitFrameMdl(
598 IN PKSPIN Pin,
599 IN PMDL Mdl OPTIONAL,
600 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
601 IN PVOID Context OPTIONAL)
602 {
603 UNIMPLEMENTED
604 return STATUS_UNSUCCESSFUL;
605 }
606
607 /*
608 @unimplemented
609 */
610 KSDDKAPI
611 BOOLEAN
612 NTAPI
613 KsProcessPinUpdate(
614 IN PKSPROCESSPIN ProcessPin)
615 {
616 UNIMPLEMENTED
617 return FALSE;
618 }
619
620 /*
621 @unimplemented
622 */
623 KSDDKAPI
624 PKSSTREAM_POINTER
625 NTAPI
626 KsPinGetLeadingEdgeStreamPointer(
627 IN PKSPIN Pin,
628 IN KSSTREAM_POINTER_STATE State)
629 {
630 UNIMPLEMENTED
631 DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x\n", Pin, State);
632 return NULL;
633 }
634
635 /*
636 @unimplemented
637 */
638 KSDDKAPI
639 PKSSTREAM_POINTER
640 NTAPI
641 KsPinGetTrailingEdgeStreamPointer(
642 IN PKSPIN Pin,
643 IN KSSTREAM_POINTER_STATE State)
644 {
645 UNIMPLEMENTED
646 return NULL;
647 }
648
649 /*
650 @unimplemented
651 */
652 KSDDKAPI
653 NTSTATUS
654 NTAPI
655 KsStreamPointerSetStatusCode(
656 IN PKSSTREAM_POINTER StreamPointer,
657 IN NTSTATUS Status)
658 {
659 UNIMPLEMENTED
660 return STATUS_UNSUCCESSFUL;
661 }
662
663 /*
664 @unimplemented
665 */
666 KSDDKAPI
667 NTSTATUS
668 NTAPI
669 KsStreamPointerLock(
670 IN PKSSTREAM_POINTER StreamPointer)
671 {
672 UNIMPLEMENTED
673 return STATUS_UNSUCCESSFUL;
674 }
675
676 /*
677 @unimplemented
678 */
679 KSDDKAPI
680 VOID
681 NTAPI
682 KsStreamPointerUnlock(
683 IN PKSSTREAM_POINTER StreamPointer,
684 IN BOOLEAN Eject)
685 {
686 UNIMPLEMENTED
687 DPRINT("KsStreamPointerUnlock\n");
688 }
689
690 /*
691 @unimplemented
692 */
693 KSDDKAPI
694 VOID
695 NTAPI
696 KsStreamPointerAdvanceOffsetsAndUnlock(
697 IN PKSSTREAM_POINTER StreamPointer,
698 IN ULONG InUsed,
699 IN ULONG OutUsed,
700 IN BOOLEAN Eject)
701 {
702 DPRINT("KsStreamPointerAdvanceOffsets\n");
703
704 UNIMPLEMENTED
705 }
706
707 /*
708 @implemented
709 */
710 KSDDKAPI
711 VOID
712 NTAPI
713 KsStreamPointerDelete(
714 IN PKSSTREAM_POINTER StreamPointer)
715 {
716 IKsPinImpl * This;
717 PKSISTREAM_POINTER Cur, Last;
718 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
719
720 DPRINT("KsStreamPointerDelete\n");
721
722 This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
723
724 /* point to first stream pointer */
725 Last = NULL;
726 Cur = This->ClonedStreamPointer;
727
728 while(Cur != Pointer && Cur)
729 {
730 Last = Cur;
731 /* iterate to next cloned pointer */
732 Cur = Cur->Next;
733 }
734
735 if (!Cur)
736 {
737 /* you naughty driver */
738 return;
739 }
740
741 if (!Last)
742 {
743 /* remove first cloned pointer */
744 This->ClonedStreamPointer = Pointer->Next;
745 }
746 else
747 {
748 Last->Next = Pointer->Next;
749 }
750
751 /* FIXME make sure no timeouts are pending */
752 FreeItem(Pointer);
753 }
754
755 /*
756 @unimplemented
757 */
758 KSDDKAPI
759 NTSTATUS
760 NTAPI
761 KsStreamPointerClone(
762 IN PKSSTREAM_POINTER StreamPointer,
763 IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
764 IN ULONG ContextSize,
765 OUT PKSSTREAM_POINTER* CloneStreamPointer)
766 {
767 UNIMPLEMENTED
768 DPRINT("KsStreamPointerClone\n");
769 return STATUS_NOT_IMPLEMENTED;
770 }
771
772 /*
773 @unimplemented
774 */
775 KSDDKAPI
776 NTSTATUS
777 NTAPI
778 KsStreamPointerAdvanceOffsets(
779 IN PKSSTREAM_POINTER StreamPointer,
780 IN ULONG InUsed,
781 IN ULONG OutUsed,
782 IN BOOLEAN Eject)
783 {
784 UNIMPLEMENTED
785 return STATUS_NOT_IMPLEMENTED;
786 }
787
788 /*
789 @unimplemented
790 */
791 KSDDKAPI
792 NTSTATUS
793 NTAPI
794 KsStreamPointerAdvance(
795 IN PKSSTREAM_POINTER StreamPointer)
796 {
797 UNIMPLEMENTED
798 return STATUS_NOT_IMPLEMENTED;
799 }
800
801 /*
802 @unimplemented
803 */
804 KSDDKAPI
805 PMDL
806 NTAPI
807 KsStreamPointerGetMdl(
808 IN PKSSTREAM_POINTER StreamPointer)
809 {
810 UNIMPLEMENTED
811 return NULL;
812 }
813
814 /*
815 @unimplemented
816 */
817 KSDDKAPI
818 PIRP
819 NTAPI
820 KsStreamPointerGetIrp(
821 IN PKSSTREAM_POINTER StreamPointer,
822 OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
823 OUT PBOOLEAN LastFrameInIrp OPTIONAL)
824 {
825 UNIMPLEMENTED
826 return NULL;
827 }
828
829 /*
830 @implemented
831 */
832 KSDDKAPI
833 VOID
834 NTAPI
835 KsStreamPointerScheduleTimeout(
836 IN PKSSTREAM_POINTER StreamPointer,
837 IN PFNKSSTREAMPOINTER Callback,
838 IN ULONGLONG Interval)
839 {
840 LARGE_INTEGER DueTime;
841 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
842
843 /* setup timer callback */
844 Pointer->Callback = Callback;
845
846 /* setup expiration */
847 DueTime.QuadPart = (LONGLONG)Interval;
848
849 /* setup the timer */
850 KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
851
852 }
853
854 /*
855 @implemented
856 */
857 KSDDKAPI
858 VOID
859 NTAPI
860 KsStreamPointerCancelTimeout(
861 IN PKSSTREAM_POINTER StreamPointer)
862 {
863 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
864
865 KeCancelTimer(&Pointer->Timer);
866
867 }
868
869 /*
870 @implemented
871 */
872 KSDDKAPI
873 PKSSTREAM_POINTER
874 NTAPI
875 KsPinGetFirstCloneStreamPointer(
876 IN PKSPIN Pin)
877 {
878 IKsPinImpl * This;
879
880 DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
881
882 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
883 /* return first cloned stream pointer */
884 return &This->ClonedStreamPointer->StreamPointer;
885 }
886
887 /*
888 @implemented
889 */
890 KSDDKAPI
891 PKSSTREAM_POINTER
892 NTAPI
893 KsStreamPointerGetNextClone(
894 IN PKSSTREAM_POINTER StreamPointer)
895 {
896 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
897
898 DPRINT("KsStreamPointerGetNextClone\n");
899
900 /* is there a another cloned stream pointer */
901 if (!Pointer->Next)
902 return NULL;
903
904 /* return next stream pointer */
905 return &Pointer->Next->StreamPointer;
906 }
907
908 NTSTATUS
909 IKsPin_DispatchKsProperty(
910 PDEVICE_OBJECT DeviceObject,
911 PIRP Irp,
912 IKsPinImpl * This)
913 {
914 NTSTATUS Status;
915 PKSPROPERTY Property;
916 PIO_STACK_LOCATION IoStack;
917 UNICODE_STRING GuidString;
918 ULONG PropertySetsCount = 0, PropertyItemSize = 0;
919 const KSPROPERTY_SET* PropertySets = NULL;
920
921 /* sanity check */
922 ASSERT(This->Pin.Descriptor);
923
924 /* get current irp stack */
925 IoStack = IoGetCurrentIrpStackLocation(Irp);
926
927
928 if (This->Pin.Descriptor->AutomationTable)
929 {
930 /* use available driver property sets */
931 PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
932 PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets;
933 PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
934 }
935
936
937 /* try driver provided property sets */
938 Status = KspPropertyHandler(Irp,
939 PropertySetsCount,
940 PropertySets,
941 NULL,
942 PropertyItemSize);
943
944 DPRINT("IKsPin_DispatchKsProperty PropertySetCount %lu Status %lu\n", PropertySetsCount, Status);
945
946 if (Status != STATUS_NOT_FOUND)
947 {
948 /* property was handled by driver */
949 if (Status != STATUS_PENDING)
950 {
951 Irp->IoStatus.Status = Status;
952 IoCompleteRequest(Irp, IO_NO_INCREMENT);
953 }
954 return Status;
955 }
956
957 /* property was not handled */
958 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
959
960 RtlStringFromGUID(&Property->Set, &GuidString);
961 DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
962 RtlFreeUnicodeString(&GuidString);
963
964 Irp->IoStatus.Status = STATUS_NOT_FOUND;
965 IoCompleteRequest(Irp, IO_NO_INCREMENT);
966
967 return STATUS_NOT_FOUND;
968
969 }
970
971 NTSTATUS
972 NTAPI
973 IKsPin_DispatchDeviceIoControl(
974 IN PDEVICE_OBJECT DeviceObject,
975 IN PIRP Irp)
976 {
977 PIO_STACK_LOCATION IoStack;
978 PKSIOBJECT_HEADER ObjectHeader;
979 IKsPinImpl * This;
980 NTSTATUS Status = STATUS_SUCCESS;
981
982 /* get current irp stack */
983 IoStack = IoGetCurrentIrpStackLocation(Irp);
984
985 /* sanity check */
986 ASSERT(IoStack->FileObject);
987 ASSERT(IoStack->FileObject->FsContext2);
988
989 /* get the object header */
990 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
991
992 /* locate ks pin implemention from KSPIN offset */
993 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
994
995 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
996 {
997 /* handle ks properties */
998 return IKsPin_DispatchKsProperty(DeviceObject, Irp, This);
999 }
1000
1001
1002 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_WRITE_STREAM && IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_READ_STREAM)
1003 {
1004 UNIMPLEMENTED;
1005 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1006 Irp->IoStatus.Information = 0;
1007 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1008 return STATUS_NOT_IMPLEMENTED;
1009 }
1010
1011 /* mark irp as pending */
1012 IoMarkIrpPending(Irp);
1013
1014 /* add irp to cancelable queue */
1015 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1016
1017 if (This->Pin.Descriptor->Dispatch->Process)
1018 {
1019 /* it is a pin centric avstream */
1020 Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
1021
1022 /* TODO */
1023 }
1024 else
1025 {
1026 /* TODO
1027 * filter-centric avstream
1028 */
1029 UNIMPLEMENTED
1030 }
1031
1032 return Status;
1033 }
1034
1035 NTSTATUS
1036 NTAPI
1037 IKsPin_Close(
1038 IN PDEVICE_OBJECT DeviceObject,
1039 IN PIRP Irp)
1040 {
1041 PIO_STACK_LOCATION IoStack;
1042 PKSIOBJECT_HEADER ObjectHeader;
1043 IKsPinImpl * This;
1044 NTSTATUS Status = STATUS_SUCCESS;
1045
1046 /* get current irp stack */
1047 IoStack = IoGetCurrentIrpStackLocation(Irp);
1048
1049 /* sanity check */
1050 ASSERT(IoStack->FileObject);
1051 ASSERT(IoStack->FileObject->FsContext2);
1052
1053 /* get the object header */
1054 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1055
1056 /* locate ks pin implemention fro KSPIN offset */
1057 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
1058
1059 /* acquire filter control mutex */
1060 KsFilterAcquireControl(This->BasicHeader.Parent.KsFilter);
1061
1062 if (This->Pin.Descriptor->Dispatch->Close)
1063 {
1064 /* call pin close routine */
1065 Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
1066
1067 if (!NT_SUCCESS(Status))
1068 {
1069 /* abort closing */
1070 Irp->IoStatus.Status = Status;
1071 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1072 return Status;
1073 }
1074
1075 /* FIXME remove pin from filter pin list and decrement reference count */
1076
1077 if (Status != STATUS_PENDING)
1078 {
1079 Irp->IoStatus.Status = Status;
1080 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1081 return Status;
1082 }
1083 }
1084
1085 return Status;
1086 }
1087
1088 NTSTATUS
1089 NTAPI
1090 IKsPin_DispatchCreateAllocator(
1091 IN PDEVICE_OBJECT DeviceObject,
1092 IN PIRP Irp)
1093 {
1094 UNIMPLEMENTED;
1095
1096 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1097 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1098 return STATUS_NOT_IMPLEMENTED;
1099 }
1100
1101 NTSTATUS
1102 NTAPI
1103 IKsPin_DispatchCreateClock(
1104 IN PDEVICE_OBJECT DeviceObject,
1105 IN PIRP Irp)
1106 {
1107 UNIMPLEMENTED;
1108
1109 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1110 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1111 return STATUS_NOT_IMPLEMENTED;
1112 }
1113
1114 NTSTATUS
1115 NTAPI
1116 IKsPin_DispatchCreateNode(
1117 IN PDEVICE_OBJECT DeviceObject,
1118 IN PIRP Irp)
1119 {
1120 UNIMPLEMENTED;
1121
1122 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1123 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1124 return STATUS_NOT_IMPLEMENTED;
1125 }
1126
1127 static KSDISPATCH_TABLE PinDispatchTable =
1128 {
1129 IKsPin_DispatchDeviceIoControl,
1130 KsDispatchInvalidDeviceRequest,
1131 KsDispatchInvalidDeviceRequest,
1132 KsDispatchInvalidDeviceRequest,
1133 IKsPin_Close,
1134 KsDispatchQuerySecurity,
1135 KsDispatchSetSecurity,
1136 KsDispatchFastIoDeviceControlFailure,
1137 KsDispatchFastReadFailure,
1138 KsDispatchFastReadFailure
1139 };
1140
1141 NTSTATUS
1142 KspCreatePin(
1143 IN PDEVICE_OBJECT DeviceObject,
1144 IN PIRP Irp,
1145 IN PKSDEVICE KsDevice,
1146 IN IKsFilterFactory * FilterFactory,
1147 IN IKsFilter* Filter,
1148 IN PKSPIN_CONNECT Connect,
1149 IN KSPIN_DESCRIPTOR_EX* Descriptor)
1150 {
1151 IKsPinImpl * This;
1152 PIO_STACK_LOCATION IoStack;
1153 IKsDevice * Device;
1154 PDEVICE_EXTENSION DeviceExtension;
1155 PKSOBJECT_CREATE_ITEM CreateItem;
1156 NTSTATUS Status;
1157 PKSDATAFORMAT DataFormat;
1158
1159 /* sanity checks */
1160 ASSERT(Descriptor->Dispatch);
1161
1162 DPRINT("KspCreatePin\n");
1163
1164 /* get current irp stack */
1165 IoStack = IoGetCurrentIrpStackLocation(Irp);
1166
1167 /* get device extension */
1168 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1169
1170 /* get ks device interface */
1171 Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1172
1173 /* first allocate pin ctx */
1174 This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
1175 if (!This)
1176 {
1177 /* not enough memory */
1178 return STATUS_INSUFFICIENT_RESOURCES;
1179 }
1180
1181 /* allocate create item */
1182 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
1183 if (!CreateItem)
1184 {
1185 /* not enough memory */
1186 FreeItem(This);
1187 DPRINT("KspCreatePin OutOfMemory\n");
1188 return STATUS_INSUFFICIENT_RESOURCES;
1189 }
1190
1191 /* initialize basic header */
1192 This->BasicHeader.KsDevice = KsDevice;
1193 This->BasicHeader.Type = KsObjectTypePin;
1194 This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
1195 KeInitializeMutex(&This->BasicHeader.ControlMutex, 0);
1196 InitializeListHead(&This->BasicHeader.EventList);
1197 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
1198
1199 /* initialize pin */
1200 This->lpVtbl = &vt_IKsPin;
1201 This->ref = 1;
1202 This->FileObject = IoStack->FileObject;
1203 KeInitializeMutex(&This->ProcessingMutex, 0);
1204 InitializeListHead(&This->IrpList);
1205 KeInitializeSpinLock(&This->IrpListLock);
1206
1207
1208 /* allocate object bag */
1209 This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1210 if (!This->Pin.Bag)
1211 {
1212 /* not enough memory */
1213 FreeItem(This);
1214 FreeItem(CreateItem);
1215 return STATUS_INSUFFICIENT_RESOURCES;
1216 }
1217
1218 /* initialize object bag */
1219 Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */
1220
1221 /* get format */
1222 DataFormat = (PKSDATAFORMAT)(Connect + 1);
1223
1224 /* initialize ks pin descriptor */
1225 This->Pin.Descriptor = Descriptor;
1226 This->Pin.Context = NULL;
1227 This->Pin.Id = Connect->PinId;
1228 This->Pin.Communication = Descriptor->PinDescriptor.Communication;
1229 This->Pin.ConnectionIsExternal = FALSE; //FIXME
1230 RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
1231 RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
1232 RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
1233
1234 /* allocate format */
1235 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
1236 if (!NT_SUCCESS(Status))
1237 {
1238 /* failed to allocate format */
1239 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1240 FreeItem(This);
1241 FreeItem(CreateItem);
1242 return STATUS_INSUFFICIENT_RESOURCES;
1243 }
1244
1245 /* copy format */
1246 RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
1247
1248 This->Pin.AttributeList = NULL; //FIXME
1249 This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
1250 This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
1251 This->Pin.DeviceState = KSSTATE_STOP;
1252 This->Pin.ResetState = KSRESET_END;
1253 This->Pin.ClientState = KSSTATE_STOP;
1254
1255 /* intialize allocator create item */
1256 CreateItem[0].Context = (PVOID)This;
1257 CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
1258 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1259 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
1260
1261 /* intialize clock create item */
1262 CreateItem[1].Context = (PVOID)This;
1263 CreateItem[1].Create = IKsPin_DispatchCreateClock;
1264 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1265 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
1266
1267 /* intialize topology node create item */
1268 CreateItem[2].Context = (PVOID)This;
1269 CreateItem[2].Create = IKsPin_DispatchCreateNode;
1270 CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
1271 RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
1272
1273 /* now allocate object header */
1274 Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
1275 if (!NT_SUCCESS(Status))
1276 {
1277 /* failed to create object header */
1278 DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
1279 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1280 FreeItem(This);
1281 FreeItem(CreateItem);
1282
1283 /* return failure code */
1284 return Status;
1285 }
1286
1287 /* add extra info to object header */
1288 This->ObjectHeader->Type = KsObjectTypePin;
1289 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1290 This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
1291
1292 /* setup process pin */
1293 This->ProcessPin.Pin = &This->Pin;
1294 This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer;
1295
1296 if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
1297 {
1298 /* the pin is part of filter-centric processing filter
1299 * add process pin to filter
1300 */
1301
1302 Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
1303 DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
1304
1305 if (!NT_SUCCESS(Status))
1306 {
1307 /* failed to add process pin */
1308 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1309 KsFreeObjectHeader(&This->ObjectHeader);
1310
1311 /* return failure code */
1312 return Status;
1313 }
1314 }
1315
1316 /* FIXME add pin instance to filter instance */
1317
1318 /* does the driver have a pin dispatch */
1319 if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
1320 {
1321 /* now inform the driver to create a new pin */
1322 Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
1323 DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
1324 }
1325
1326 DPRINT("KspCreatePin Status %lx\n", Status);
1327
1328 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1329 {
1330 /* failed to create pin, release resources */
1331 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
1332 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1333 FreeItem(This);
1334
1335 /* return failure code */
1336 return Status;
1337 }
1338
1339 return Status;
1340 }