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