- Implement KsGetFirstChild, KsGetNextSibling
[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 UNIMPLEMENTED
343 }
344
345 /*
346 @unimplemented
347 */
348 NTSTATUS
349 NTAPI
350 KsPinGetAvailableByteCount(
351 IN PKSPIN Pin,
352 OUT PLONG InputDataBytes OPTIONAL,
353 OUT PLONG OutputBufferBytes OPTIONAL)
354 {
355 UNIMPLEMENTED
356 return STATUS_NOT_IMPLEMENTED;
357 }
358
359 /*
360 @unimplemented
361 */
362 NTSTATUS
363 NTAPI
364 KsPinGetConnectedFilterInterface(
365 IN PKSPIN Pin,
366 IN const GUID* InterfaceId,
367 OUT PVOID* Interface)
368 {
369 UNIMPLEMENTED
370 return STATUS_NOT_IMPLEMENTED;
371 }
372
373 /*
374 @unimplemented
375 */
376 PDEVICE_OBJECT
377 NTAPI
378 KsPinGetConnectedPinDeviceObject(
379 IN PKSPIN Pin)
380 {
381 UNIMPLEMENTED
382 return NULL;
383 }
384
385 /*
386 @unimplemented
387 */
388 PFILE_OBJECT
389 NTAPI
390 KsPinGetConnectedPinFileObject(
391 IN PKSPIN Pin)
392 {
393 UNIMPLEMENTED
394 return NULL;
395 }
396
397 /*
398 @unimplemented
399 */
400 NTSTATUS
401 NTAPI
402 KsPinGetConnectedPinInterface(
403 IN PKSPIN Pin,
404 IN const GUID* InterfaceId,
405 OUT PVOID* Interface)
406 {
407 UNIMPLEMENTED
408 return STATUS_NOT_IMPLEMENTED;
409 }
410
411 /*
412 @unimplemented
413 */
414 VOID
415 NTAPI
416 KsPinGetCopyRelationships(
417 IN PKSPIN Pin,
418 OUT PKSPIN* CopySource,
419 OUT PKSPIN* DelegateBranch)
420 {
421 UNIMPLEMENTED
422 }
423
424 /*
425 @implemented
426 */
427 PKSPIN
428 NTAPI
429 KsPinGetNextSiblingPin(
430 IN PKSPIN Pin)
431 {
432 return KsGetNextSibling((PVOID)Pin);
433 }
434
435 /*
436 @implemented
437 */
438 PKSFILTER
439 NTAPI
440 KsPinGetParentFilter(
441 IN PKSPIN Pin)
442 {
443 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
444
445 /* return parent filter */
446 return This->BasicHeader.Parent.KsFilter;
447 }
448
449 /*
450 @unimplemented
451 */
452 NTSTATUS
453 NTAPI
454 KsPinGetReferenceClockInterface(
455 IN PKSPIN Pin,
456 OUT PIKSREFERENCECLOCK* Interface)
457 {
458 UNIMPLEMENTED
459 return STATUS_UNSUCCESSFUL;
460 }
461
462 /*
463 @implemented
464 */
465 VOID
466 NTAPI
467 KsPinRegisterFrameReturnCallback(
468 IN PKSPIN Pin,
469 IN PFNKSPINFRAMERETURN FrameReturn)
470 {
471 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
472
473 /* register frame return callback */
474 This->FrameReturn = FrameReturn;
475 }
476
477 /*
478 @implemented
479 */
480 VOID
481 NTAPI
482 KsPinRegisterHandshakeCallback(
483 IN PKSPIN Pin,
484 IN PFNKSPINHANDSHAKE Handshake)
485 {
486 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
487
488 /* register private protocol handshake callback */
489 This->Handshake = Handshake;
490 }
491
492 /*
493 @implemented
494 */
495 VOID
496 NTAPI
497 KsPinRegisterIrpCompletionCallback(
498 IN PKSPIN Pin,
499 IN PFNKSPINIRPCOMPLETION IrpCompletion)
500 {
501 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
502
503 /* register irp completion callback */
504 This->IrpCompletion = IrpCompletion;
505 }
506
507 /*
508 @implemented
509 */
510 VOID
511 NTAPI
512 KsPinRegisterPowerCallbacks(
513 IN PKSPIN Pin,
514 IN PFNKSPINPOWER Sleep OPTIONAL,
515 IN PFNKSPINPOWER Wake OPTIONAL)
516 {
517 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
518
519 /* register power callbacks */
520 This->Sleep = Sleep;
521 This->Wake = Wake;
522 }
523
524 /*
525 @implemented
526 */
527 VOID
528 NTAPI
529 KsPinReleaseProcessingMutex(
530 IN PKSPIN Pin)
531 {
532 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
533
534 /* release processing mutex */
535 KeReleaseMutex(&This->ProcessingMutex, FALSE);
536 }
537
538 /*
539 @implemented
540 */
541 KSDDKAPI
542 PKSPIN
543 NTAPI
544 KsGetPinFromIrp(
545 IN PIRP Irp)
546 {
547 PKSIOBJECT_HEADER ObjectHeader;
548 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
549
550 /* get object header */
551 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
552 /* return object type */
553 return (PKSPIN)ObjectHeader->ObjectType;
554
555 }
556
557
558
559 /*
560 @unimplemented
561 */
562 VOID
563 NTAPI
564 KsPinSetPinClockTime(
565 IN PKSPIN Pin,
566 IN LONGLONG Time)
567 {
568 UNIMPLEMENTED
569 }
570
571 /*
572 @unimplemented
573 */
574 NTSTATUS
575 NTAPI
576 KsPinSubmitFrame(
577 IN PKSPIN Pin,
578 IN PVOID Data OPTIONAL,
579 IN ULONG Size OPTIONAL,
580 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
581 IN PVOID Context OPTIONAL)
582 {
583 UNIMPLEMENTED
584 return STATUS_UNSUCCESSFUL;
585 }
586
587 /*
588 @unimplemented
589 */
590 KSDDKAPI
591 NTSTATUS
592 NTAPI
593 KsPinSubmitFrameMdl(
594 IN PKSPIN Pin,
595 IN PMDL Mdl OPTIONAL,
596 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
597 IN PVOID Context OPTIONAL)
598 {
599 UNIMPLEMENTED
600 return STATUS_UNSUCCESSFUL;
601 }
602
603 /*
604 @unimplemented
605 */
606 KSDDKAPI
607 BOOLEAN
608 NTAPI
609 KsProcessPinUpdate(
610 IN PKSPROCESSPIN ProcessPin)
611 {
612 UNIMPLEMENTED
613 return FALSE;
614 }
615
616 /*
617 @unimplemented
618 */
619 KSDDKAPI
620 PKSSTREAM_POINTER
621 NTAPI
622 KsPinGetLeadingEdgeStreamPointer(
623 IN PKSPIN Pin,
624 IN KSSTREAM_POINTER_STATE State)
625 {
626 UNIMPLEMENTED
627 return NULL;
628 }
629
630 /*
631 @unimplemented
632 */
633 KSDDKAPI
634 PKSSTREAM_POINTER
635 NTAPI
636 KsPinGetTrailingEdgeStreamPointer(
637 IN PKSPIN Pin,
638 IN KSSTREAM_POINTER_STATE State)
639 {
640 UNIMPLEMENTED
641 return NULL;
642 }
643
644 /*
645 @unimplemented
646 */
647 KSDDKAPI
648 NTSTATUS
649 NTAPI
650 KsStreamPointerSetStatusCode(
651 IN PKSSTREAM_POINTER StreamPointer,
652 IN NTSTATUS Status)
653 {
654 UNIMPLEMENTED
655 return STATUS_UNSUCCESSFUL;
656 }
657
658 /*
659 @unimplemented
660 */
661 KSDDKAPI
662 NTSTATUS
663 NTAPI
664 KsStreamPointerLock(
665 IN PKSSTREAM_POINTER StreamPointer)
666 {
667 UNIMPLEMENTED
668 return STATUS_UNSUCCESSFUL;
669 }
670
671 /*
672 @unimplemented
673 */
674 KSDDKAPI
675 VOID
676 NTAPI
677 KsStreamPointerUnlock(
678 IN PKSSTREAM_POINTER StreamPointer,
679 IN BOOLEAN Eject)
680 {
681 UNIMPLEMENTED
682 }
683
684 /*
685 @unimplemented
686 */
687 KSDDKAPI
688 VOID
689 NTAPI
690 KsStreamPointerAdvanceOffsetsAndUnlock(
691 IN PKSSTREAM_POINTER StreamPointer,
692 IN ULONG InUsed,
693 IN ULONG OutUsed,
694 IN BOOLEAN Eject)
695 {
696 UNIMPLEMENTED
697 }
698
699 /*
700 @implemented
701 */
702 KSDDKAPI
703 VOID
704 NTAPI
705 KsStreamPointerDelete(
706 IN PKSSTREAM_POINTER StreamPointer)
707 {
708 IKsPinImpl * This;
709 PKSISTREAM_POINTER Cur, Last;
710 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
711
712 This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
713
714 /* point to first stream pointer */
715 Last = NULL;
716 Cur = This->ClonedStreamPointer;
717
718 while(Cur != Pointer && Cur)
719 {
720 Last = Cur;
721 /* iterate to next cloned pointer */
722 Cur = Cur->Next;
723 }
724
725 if (!Cur)
726 {
727 /* you naughty driver */
728 return;
729 }
730
731 if (!Last)
732 {
733 /* remove first cloned pointer */
734 This->ClonedStreamPointer = Pointer->Next;
735 }
736 else
737 {
738 Last->Next = Pointer->Next;
739 }
740
741 /* FIXME make sure no timeouts are pending */
742 FreeItem(Pointer);
743 }
744
745 /*
746 @unimplemented
747 */
748 KSDDKAPI
749 NTSTATUS
750 NTAPI
751 KsStreamPointerClone(
752 IN PKSSTREAM_POINTER StreamPointer,
753 IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
754 IN ULONG ContextSize,
755 OUT PKSSTREAM_POINTER* CloneStreamPointer)
756 {
757 UNIMPLEMENTED
758 return STATUS_NOT_IMPLEMENTED;
759 }
760
761 /*
762 @unimplemented
763 */
764 KSDDKAPI
765 NTSTATUS
766 NTAPI
767 KsStreamPointerAdvanceOffsets(
768 IN PKSSTREAM_POINTER StreamPointer,
769 IN ULONG InUsed,
770 IN ULONG OutUsed,
771 IN BOOLEAN Eject)
772 {
773 UNIMPLEMENTED
774 return STATUS_NOT_IMPLEMENTED;
775 }
776
777 /*
778 @unimplemented
779 */
780 KSDDKAPI
781 NTSTATUS
782 NTAPI
783 KsStreamPointerAdvance(
784 IN PKSSTREAM_POINTER StreamPointer)
785 {
786 UNIMPLEMENTED
787 return STATUS_NOT_IMPLEMENTED;
788 }
789
790 /*
791 @unimplemented
792 */
793 KSDDKAPI
794 PMDL
795 NTAPI
796 KsStreamPointerGetMdl(
797 IN PKSSTREAM_POINTER StreamPointer)
798 {
799 UNIMPLEMENTED
800 return NULL;
801 }
802
803 /*
804 @unimplemented
805 */
806 KSDDKAPI
807 PIRP
808 NTAPI
809 KsStreamPointerGetIrp(
810 IN PKSSTREAM_POINTER StreamPointer,
811 OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
812 OUT PBOOLEAN LastFrameInIrp OPTIONAL)
813 {
814 UNIMPLEMENTED
815 return NULL;
816 }
817
818 /*
819 @implemented
820 */
821 KSDDKAPI
822 VOID
823 NTAPI
824 KsStreamPointerScheduleTimeout(
825 IN PKSSTREAM_POINTER StreamPointer,
826 IN PFNKSSTREAMPOINTER Callback,
827 IN ULONGLONG Interval)
828 {
829 LARGE_INTEGER DueTime;
830 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
831
832 /* setup timer callback */
833 Pointer->Callback = Callback;
834
835 /* setup expiration */
836 DueTime.QuadPart = (LONGLONG)Interval;
837
838 /* setup the timer */
839 KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
840
841 }
842
843 /*
844 @implemented
845 */
846 KSDDKAPI
847 VOID
848 NTAPI
849 KsStreamPointerCancelTimeout(
850 IN PKSSTREAM_POINTER StreamPointer)
851 {
852 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
853
854 KeCancelTimer(&Pointer->Timer);
855
856 }
857
858 /*
859 @implemented
860 */
861 KSDDKAPI
862 PKSSTREAM_POINTER
863 NTAPI
864 KsPinGetFirstCloneStreamPointer(
865 IN PKSPIN Pin)
866 {
867 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
868 /* return first cloned stream pointer */
869 return &This->ClonedStreamPointer->StreamPointer;
870 }
871
872 /*
873 @implemented
874 */
875 KSDDKAPI
876 PKSSTREAM_POINTER
877 NTAPI
878 KsStreamPointerGetNextClone(
879 IN PKSSTREAM_POINTER StreamPointer)
880 {
881 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
882
883 /* is there a another cloned stream pointer */
884 if (!Pointer->Next)
885 return NULL;
886
887 /* return next stream pointer */
888 return &Pointer->Next->StreamPointer;
889 }
890
891 NTSTATUS
892 NTAPI
893 IKsPin_DispatchDeviceIoControl(
894 IN PDEVICE_OBJECT DeviceObject,
895 IN PIRP Irp)
896 {
897 PIO_STACK_LOCATION IoStack;
898 PKSIOBJECT_HEADER ObjectHeader;
899 IKsPinImpl * This;
900 NTSTATUS Status = STATUS_SUCCESS;
901
902 /* get current irp stack */
903 IoStack = IoGetCurrentIrpStackLocation(Irp);
904
905 /* sanity check */
906 ASSERT(IoStack->FileObject);
907 ASSERT(IoStack->FileObject->FsContext);
908
909 /* get the object header */
910 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
911
912 /* locate ks pin implemention fro KSPIN offset */
913 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
914
915 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_WRITE_STREAM && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
916 {
917 UNIMPLEMENTED;
918 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
919 Irp->IoStatus.Information = 0;
920 IoCompleteRequest(Irp, IO_NO_INCREMENT);
921 return STATUS_NOT_IMPLEMENTED;
922 }
923
924 /* mark irp as pending */
925 IoMarkIrpPending(Irp);
926
927 /* add irp to cancelable queue */
928 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
929
930 if (This->Pin.Descriptor->Dispatch->Process)
931 {
932 /* it is a pin centric avstream */
933 Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
934
935 /* TODO */
936 }
937 else
938 {
939 /* TODO
940 * filter-centric avstream
941 */
942 UNIMPLEMENTED
943 }
944
945 return Status;
946 }
947
948 NTSTATUS
949 NTAPI
950 IKsPin_Close(
951 IN PDEVICE_OBJECT DeviceObject,
952 IN PIRP Irp)
953 {
954 PIO_STACK_LOCATION IoStack;
955 PKSIOBJECT_HEADER ObjectHeader;
956 IKsPinImpl * This;
957 NTSTATUS Status = STATUS_SUCCESS;
958
959 /* get current irp stack */
960 IoStack = IoGetCurrentIrpStackLocation(Irp);
961
962 /* sanity check */
963 ASSERT(IoStack->FileObject);
964 ASSERT(IoStack->FileObject->FsContext);
965
966 /* get the object header */
967 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
968
969 /* locate ks pin implemention fro KSPIN offset */
970 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
971
972 /* acquire filter control mutex */
973 KsFilterAcquireControl(This->BasicHeader.Parent.KsFilter);
974
975 if (This->Pin.Descriptor->Dispatch->Close)
976 {
977 /* call pin close routine */
978 Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
979
980 if (!NT_SUCCESS(Status))
981 {
982 /* abort closing */
983 Irp->IoStatus.Status = Status;
984 IoCompleteRequest(Irp, IO_NO_INCREMENT);
985 return Status;
986 }
987
988 /* FIXME remove pin from filter pin list and decrement reference count */
989
990 if (Status != STATUS_PENDING)
991 {
992 Irp->IoStatus.Status = Status;
993 IoCompleteRequest(Irp, IO_NO_INCREMENT);
994 return Status;
995 }
996 }
997
998 return Status;
999 }
1000
1001 NTSTATUS
1002 NTAPI
1003 IKsPin_DispatchCreateAllocator(
1004 IN PDEVICE_OBJECT DeviceObject,
1005 IN PIRP Irp)
1006 {
1007 UNIMPLEMENTED;
1008
1009 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1010 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1011 return STATUS_NOT_IMPLEMENTED;
1012 }
1013
1014 NTSTATUS
1015 NTAPI
1016 IKsPin_DispatchCreateClock(
1017 IN PDEVICE_OBJECT DeviceObject,
1018 IN PIRP Irp)
1019 {
1020 UNIMPLEMENTED;
1021
1022 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1023 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1024 return STATUS_NOT_IMPLEMENTED;
1025 }
1026
1027 NTSTATUS
1028 NTAPI
1029 IKsPin_DispatchCreateNode(
1030 IN PDEVICE_OBJECT DeviceObject,
1031 IN PIRP Irp)
1032 {
1033 UNIMPLEMENTED;
1034
1035 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1036 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1037 return STATUS_NOT_IMPLEMENTED;
1038 }
1039
1040 static KSDISPATCH_TABLE PinDispatchTable =
1041 {
1042 IKsPin_DispatchDeviceIoControl,
1043 KsDispatchInvalidDeviceRequest,
1044 KsDispatchInvalidDeviceRequest,
1045 KsDispatchInvalidDeviceRequest,
1046 IKsPin_Close,
1047 KsDispatchQuerySecurity,
1048 KsDispatchSetSecurity,
1049 KsDispatchFastIoDeviceControlFailure,
1050 KsDispatchFastReadFailure,
1051 KsDispatchFastReadFailure
1052 };
1053
1054 NTSTATUS
1055 KspCreatePin(
1056 IN PDEVICE_OBJECT DeviceObject,
1057 IN PIRP Irp,
1058 IN PKSDEVICE KsDevice,
1059 IN IKsFilterFactory * FilterFactory,
1060 IN IKsFilter* Filter,
1061 IN PKSPIN_CONNECT Connect,
1062 IN KSPIN_DESCRIPTOR_EX* Descriptor)
1063 {
1064 IKsPinImpl * This;
1065 PIO_STACK_LOCATION IoStack;
1066 IKsDevice * Device;
1067 PDEVICE_EXTENSION DeviceExtension;
1068 PKSOBJECT_CREATE_ITEM CreateItem;
1069 NTSTATUS Status;
1070
1071 /* sanity checks */
1072 ASSERT(Descriptor->Dispatch);
1073 ASSERT(Descriptor->Dispatch->Create);
1074
1075 /* get current irp stack */
1076 IoStack = IoGetCurrentIrpStackLocation(Irp);
1077
1078 /* get device extension */
1079 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1080
1081 /* get ks device interface */
1082 Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1083
1084 /* first allocate pin ctx */
1085 This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
1086 if (!This)
1087 {
1088 /* not enough memory */
1089 return STATUS_INSUFFICIENT_RESOURCES;
1090 }
1091
1092 /* allocate create item */
1093 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
1094 if (!CreateItem)
1095 {
1096 /* not enough memory */
1097 FreeItem(This);
1098 return STATUS_INSUFFICIENT_RESOURCES;
1099 }
1100
1101 /* initialize basic header */
1102 This->BasicHeader.KsDevice = KsDevice;
1103 This->BasicHeader.Type = KsObjectTypePin;
1104 This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
1105 KeInitializeMutex(&This->BasicHeader.ControlMutex, 0);
1106 InitializeListHead(&This->BasicHeader.EventList);
1107 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
1108
1109 /* initialize pin */
1110 This->lpVtbl = &vt_IKsPin;
1111 This->ref = 1;
1112 This->FileObject = IoStack->FileObject;
1113 KeInitializeMutex(&This->ProcessingMutex, 0);
1114 InitializeListHead(&This->IrpList);
1115 KeInitializeSpinLock(&This->IrpListLock);
1116
1117 /* initialize ks pin descriptor */
1118 This->Pin.Descriptor = Descriptor;
1119 This->Pin.Id = Connect->PinId;
1120
1121 /* allocate object bag */
1122 This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1123 if (!This->Pin.Bag)
1124 {
1125 /* not enough memory */
1126 FreeItem(This);
1127 FreeItem(CreateItem);
1128 return STATUS_INSUFFICIENT_RESOURCES;
1129 }
1130
1131 /* initialize object bag */
1132 Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */
1133
1134 This->Pin.Communication = Descriptor->PinDescriptor.Communication;
1135 This->Pin.ConnectionIsExternal = FALSE; /* FIXME */
1136 //FIXME This->Pin.ConnectionInterface = Descriptor->PinDescriptor.Interfaces;
1137 //FIXME This->Pin.ConnectionMedium = Descriptor->PinDescriptor.Mediums;
1138 //FIXME This->Pin.ConnectionPriority = KSPRIORITY_NORMAL;
1139 This->Pin.ConnectionFormat = (PKSDATAFORMAT) (Connect + 1);
1140 This->Pin.AttributeList = NULL; //FIXME
1141 This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
1142 This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
1143 This->Pin.DeviceState = KSSTATE_STOP;
1144 This->Pin.ResetState = KSRESET_END;
1145 This->Pin.ClientState = KSSTATE_STOP;
1146
1147 /* intialize allocator create item */
1148 CreateItem[0].Context = (PVOID)This;
1149 CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
1150 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1151 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
1152
1153 /* intialize clock create item */
1154 CreateItem[1].Context = (PVOID)This;
1155 CreateItem[1].Create = IKsPin_DispatchCreateClock;
1156 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1157 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
1158
1159 /* intialize topology node create item */
1160 CreateItem[2].Context = (PVOID)This;
1161 CreateItem[2].Create = IKsPin_DispatchCreateNode;
1162 CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
1163 RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
1164
1165 /* now allocate object header */
1166 Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
1167 if (!NT_SUCCESS(Status))
1168 {
1169 /* failed to create object header */
1170 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1171 FreeItem(This);
1172 FreeItem(CreateItem);
1173
1174 /* return failure code */
1175 return Status;
1176 }
1177
1178 /* add extra info to object header */
1179 This->ObjectHeader->Type = KsObjectTypePin;
1180 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
1181 This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
1182
1183 /* setup process pin */
1184 This->ProcessPin.Pin = &This->Pin;
1185 This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer;
1186
1187 if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
1188 {
1189 /* the pin is part of filter-centric processing filter
1190 * add process pin to filter
1191 */
1192
1193 Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
1194 if (!NT_SUCCESS(Status))
1195 {
1196 /* failed to add process pin */
1197 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1198 KsFreeObjectHeader(&This->ObjectHeader);
1199
1200 /* return failure code */
1201 return Status;
1202 }
1203 }
1204
1205 /* FIXME add pin instance to filter instance */
1206
1207 /* does the driver have a pin dispatch */
1208 if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
1209 {
1210 /* now inform the driver to create a new pin */
1211 Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
1212 }
1213
1214 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1215 {
1216 /* failed to create pin, release resources */
1217 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
1218 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1219 FreeItem(This);
1220
1221 /* return failure code */
1222 return Status;
1223 }
1224
1225 return Status;
1226 }