[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 PFNKSSTREAMPOINTER Callback;
15 PIRP Irp;
16 KTIMER Timer;
17 KDPC TimerDpc;
18 struct _KSISTREAM_POINTER *Next;
19 PKSPIN Pin;
20 PVOID Data;
21 ULONG Offset;
22 ULONG Length;
23 KSSTREAM_POINTER StreamPointer;
24 KSPIN_LOCK Lock;
25 }KSISTREAM_POINTER, *PKSISTREAM_POINTER;
26
27 typedef struct
28 {
29 KSBASIC_HEADER BasicHeader;
30 KSPIN Pin;
31 PKSIOBJECT_HEADER ObjectHeader;
32 KSPROCESSPIN ProcessPin;
33 LIST_ENTRY Entry;
34
35 IKsPinVtbl *lpVtbl;
36 LONG ref;
37
38 IKsFilter * Filter;
39 KMUTEX ProcessingMutex;
40 PFILE_OBJECT FileObject;
41
42 PKSGATE AttachedGate;
43 BOOL OrGate;
44
45 LIST_ENTRY IrpList;
46 KSPIN_LOCK IrpListLock;
47 volatile LONG IrpCount;
48
49 PKSISTREAM_POINTER ClonedStreamPointer;
50 KSISTREAM_POINTER LeadingEdgeStreamPointer;
51 KSISTREAM_POINTER TrailingStreamPointer;
52
53 PFNKSPINPOWER Sleep;
54 PFNKSPINPOWER Wake;
55 PFNKSPINHANDSHAKE Handshake;
56 PFNKSPINFRAMERETURN FrameReturn;
57 PFNKSPINIRPCOMPLETION IrpCompletion;
58
59 KSCLOCK_FUNCTIONTABLE ClockTable;
60 PFILE_OBJECT ClockFileObject;
61 IKsReferenceClockVtbl * lpVtblReferenceClock;
62 PKSDEFAULTCLOCK DefaultClock;
63
64 PKSWORKER PinWorker;
65 WORK_QUEUE_ITEM PinWorkQueueItem;
66 KEVENT FrameComplete;
67 ULONG FrameSize;
68 ULONG NumFrames;
69 PDMA_ADAPTER Dma;
70 ULONG MapRegisters;
71
72 }IKsPinImpl;
73
74 NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
75 NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
76 NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
77 NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
78 NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
79 NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
80
81
82
83 DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler);
84 DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId);
85
86 //TODO
87 // KSPROPSETID_Connection
88 // KSPROPERTY_CONNECTION_ACQUIREORDERING
89 // KSPROPSETID_StreamInterface
90 // KSPROPERTY_STREAMINTERFACE_HEADERSIZE
91
92 KSPROPERTY_SET PinPropertySet[] =
93 {
94 {
95 &KSPROPSETID_Connection,
96 sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM),
97 (const KSPROPERTY_ITEM*)&PinConnectionSet,
98 0,
99 NULL
100 },
101 {
102 &KSPROPSETID_Stream,
103 sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM),
104 (const KSPROPERTY_ITEM*)&PinStreamSet,
105 0,
106 NULL
107 }
108 };
109
110 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
111 const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
112 const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
113
114 NTSTATUS
115 NTAPI
116 IKsPin_PinStreamAllocator(
117 IN PIRP Irp,
118 IN PKSIDENTIFIER Request,
119 IN OUT PVOID Data)
120 {
121 UNIMPLEMENTED
122 return STATUS_NOT_IMPLEMENTED;
123 }
124
125 NTSTATUS
126 NTAPI
127 IKsPin_PinMasterClock(
128 IN PIRP Irp,
129 IN PKSIDENTIFIER Request,
130 IN OUT PVOID Data)
131 {
132 PIO_STACK_LOCATION IoStack;
133 PKSIOBJECT_HEADER ObjectHeader;
134 IKsPinImpl * This;
135 NTSTATUS Status = STATUS_SUCCESS;
136 PHANDLE Handle;
137 PFILE_OBJECT FileObject;
138 KPROCESSOR_MODE Mode;
139 KSPROPERTY Property;
140 ULONG BytesReturned;
141
142 /* get current irp stack */
143 IoStack = IoGetCurrentIrpStackLocation(Irp);
144
145 DPRINT("IKsPin_PinMasterClock\n");
146
147 /* sanity check */
148 ASSERT(IoStack->FileObject);
149 ASSERT(IoStack->FileObject->FsContext2);
150
151 /* get the object header */
152 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
153
154 /* locate ks pin implemention from KSPIN offset */
155 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
156
157 /* acquire control mutex */
158 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
159
160 Handle = (PHANDLE)Data;
161
162 if (Request->Flags & KSPROPERTY_TYPE_GET)
163 {
164 if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
165 This->Pin.Descriptor->Dispatch &&
166 (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
167 {
168 *Handle = NULL;
169 Status = STATUS_SUCCESS;
170 }
171 else
172 {
173 /* no clock available */
174 Status = STATUS_UNSUCCESSFUL;
175 }
176 }
177 else if (Request->Flags & KSPROPERTY_TYPE_SET)
178 {
179 if (This->Pin.ClientState != KSSTATE_STOP)
180 {
181 /* can only set in stopped state */
182 Status = STATUS_INVALID_DEVICE_STATE;
183 }
184 else
185 {
186 if (*Handle)
187 {
188 Mode = ExGetPreviousMode();
189
190 Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
191
192 DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
193 if (NT_SUCCESS(Status))
194 {
195 Property.Set = KSPROPSETID_Clock;
196 Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
197 Property.Flags = KSPROPERTY_TYPE_GET;
198
199 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned);
200
201 DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status);
202
203 if (NT_SUCCESS(Status))
204 {
205 This->ClockFileObject = FileObject;
206 }
207 else
208 {
209 ObDereferenceObject(FileObject);
210 }
211 }
212 }
213 else
214 {
215 /* zeroing clock handle */
216 RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE));
217 Status = STATUS_SUCCESS;
218 if (This->ClockFileObject)
219 {
220 FileObject = This->ClockFileObject;
221 This->ClockFileObject = NULL;
222
223 ObDereferenceObject(This->ClockFileObject);
224 }
225 }
226 }
227 }
228
229 /* release processing mutex */
230 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
231
232 DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
233 return Status;
234 }
235
236
237
238 NTSTATUS
239 NTAPI
240 IKsPin_PinPipeId(
241 IN PIRP Irp,
242 IN PKSIDENTIFIER Request,
243 IN OUT PVOID Data)
244 {
245 UNIMPLEMENTED
246 return STATUS_NOT_IMPLEMENTED;
247 }
248
249
250 NTSTATUS
251 NTAPI
252 IKsPin_PinStatePropertyHandler(
253 IN PIRP Irp,
254 IN PKSIDENTIFIER Request,
255 IN OUT PVOID Data)
256 {
257 PIO_STACK_LOCATION IoStack;
258 PKSIOBJECT_HEADER ObjectHeader;
259 IKsPinImpl * This;
260 NTSTATUS Status = STATUS_SUCCESS;
261 KSSTATE OldState;
262 PKSSTATE NewState;
263
264 /* get current irp stack */
265 IoStack = IoGetCurrentIrpStackLocation(Irp);
266
267 DPRINT("IKsPin_PinStatePropertyHandler\n");
268
269 /* sanity check */
270 ASSERT(IoStack->FileObject);
271 ASSERT(IoStack->FileObject->FsContext2);
272
273 /* get the object header */
274 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
275
276 /* locate ks pin implemention from KSPIN offset */
277 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
278
279 /* acquire control mutex */
280 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
281
282 /* grab state */
283 NewState = (PKSSTATE)Data;
284
285 if (Request->Flags & KSPROPERTY_TYPE_GET)
286 {
287 *NewState = This->Pin.DeviceState;
288 Irp->IoStatus.Information = sizeof(KSSTATE);
289 }
290 else if (Request->Flags & KSPROPERTY_TYPE_SET)
291 {
292 if (This->Pin.Descriptor->Dispatch->SetDeviceState)
293 {
294 /* backup old state */
295 OldState = This->Pin.ClientState;
296
297 /* set new state */
298 This->Pin.ClientState = *NewState;
299 This->Pin.DeviceState = *NewState;
300
301 /* check if it supported */
302 Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState);
303
304 DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status);
305
306 if (!NT_SUCCESS(Status))
307 {
308 /* revert to old state */
309 This->Pin.ClientState = OldState;
310 This->Pin.DeviceState = OldState;
311 DPRINT("IKsPin_PinStatePropertyHandler failed to set state %lx Result %lx\n", *NewState, Status);
312 DbgBreakPoint();
313 }
314 else
315 {
316 /* update device state */
317 This->Pin.DeviceState = *NewState;
318 }
319 }
320 else
321 {
322 /* just set new state */
323 This->Pin.DeviceState = *NewState;
324 This->Pin.ClientState = *NewState;
325 }
326 }
327
328 /* release processing mutex */
329 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
330
331 DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
332 return Status;
333 }
334
335 NTSTATUS
336 NTAPI
337 IKsPin_PinAllocatorFramingPropertyHandler(
338 IN PIRP Irp,
339 IN PKSIDENTIFIER Request,
340 IN OUT PVOID Data)
341 {
342 UNIMPLEMENTED
343 return STATUS_NOT_IMPLEMENTED;
344 }
345
346 NTSTATUS
347 NTAPI
348 IKsPin_PinDataFormatPropertyHandler(
349 IN PIRP Irp,
350 IN PKSPROPERTY Request,
351 IN OUT PVOID Data)
352 {
353 PIO_STACK_LOCATION IoStack;
354 PKSIOBJECT_HEADER ObjectHeader;
355 IKsPinImpl * This;
356 NTSTATUS Status = STATUS_SUCCESS;
357
358 /* get current irp stack */
359 IoStack = IoGetCurrentIrpStackLocation(Irp);
360
361 DPRINT("IKsPin_PinDataFormatPropertyHandler\n");
362
363 /* sanity check */
364 ASSERT(IoStack->FileObject);
365 ASSERT(IoStack->FileObject->FsContext2);
366
367 /* get the object header */
368 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
369
370 /* locate ks pin implemention from KSPIN offset */
371 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
372
373 /* acquire control mutex */
374 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
375
376 if (Request->Flags & KSPROPERTY_TYPE_GET)
377 {
378 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize)
379 {
380 /* buffer too small */
381 Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize;
382 Status = STATUS_BUFFER_TOO_SMALL;
383 }
384 else
385 {
386 /* copy format */
387 RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize);
388 }
389 }
390 else if (Request->Flags & KSPROPERTY_TYPE_SET)
391 {
392 /* set format */
393 if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT)
394 {
395 /* format cannot be changed */
396 Status = STATUS_INVALID_DEVICE_REQUEST;
397 }
398 else
399 {
400 /* FIXME check if the format is supported */
401 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0);
402
403 if (NT_SUCCESS(Status))
404 {
405 /* store new format */
406 RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
407 }
408 }
409 }
410
411 /* release processing mutex */
412 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
413
414 DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status);
415
416 return Status;
417 }
418
419 NTSTATUS
420 NTAPI
421 IKsPin_fnQueryInterface(
422 IKsPin * iface,
423 IN REFIID refiid,
424 OUT PVOID* Output)
425 {
426 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
427
428 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
429 {
430 *Output = &This->lpVtbl;
431 _InterlockedIncrement(&This->ref);
432 return STATUS_SUCCESS;
433 }
434 DPRINT("IKsPin_fnQueryInterface\n");
435 DbgBreakPoint();
436 return STATUS_UNSUCCESSFUL;
437 }
438
439 ULONG
440 NTAPI
441 IKsPin_fnAddRef(
442 IKsPin * iface)
443 {
444 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
445
446 return InterlockedIncrement(&This->ref);
447 }
448
449 ULONG
450 NTAPI
451 IKsPin_fnRelease(
452 IKsPin * iface)
453 {
454 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
455
456 InterlockedDecrement(&This->ref);
457
458 if (This->ref == 0)
459 {
460 FreeItem(This);
461 return 0;
462 }
463 /* Return new reference count */
464 return This->ref;
465 }
466
467 NTSTATUS
468 NTAPI
469 IKsPin_fnTransferKsIrp(
470 IN IKsPin *iface,
471 IN PIRP Irp,
472 IN IKsTransport **OutTransport)
473 {
474 UNIMPLEMENTED
475 return STATUS_NOT_IMPLEMENTED;
476 }
477
478 VOID
479 NTAPI
480 IKsPin_fnDiscardKsIrp(
481 IN IKsPin *iface,
482 IN PIRP Irp,
483 IN IKsTransport * *OutTransport)
484 {
485 UNIMPLEMENTED
486 }
487
488
489 NTSTATUS
490 NTAPI
491 IKsPin_fnConnect(
492 IN IKsPin *iface,
493 IN IKsTransport * TransportIn,
494 OUT IKsTransport ** OutTransportIn,
495 OUT IKsTransport * *OutTransportOut,
496 IN KSPIN_DATAFLOW DataFlow)
497 {
498 UNIMPLEMENTED
499 return STATUS_NOT_IMPLEMENTED;
500 }
501
502 NTSTATUS
503 NTAPI
504 IKsPin_fnSetDeviceState(
505 IN IKsPin *iface,
506 IN KSSTATE OldState,
507 IN KSSTATE NewState,
508 IN IKsTransport * *OutTransport)
509 {
510 UNIMPLEMENTED
511 return STATUS_NOT_IMPLEMENTED;
512 }
513
514 VOID
515 NTAPI
516 IKsPin_fnSetResetState(
517 IN IKsPin *iface,
518 IN KSRESET ResetState,
519 OUT IKsTransport * * OutTransportOut)
520 {
521 UNIMPLEMENTED
522 }
523
524 NTSTATUS
525 NTAPI
526 IKsPin_fnGetTransportConfig(
527 IN IKsPin *iface,
528 IN struct KSPTRANSPORTCONFIG * TransportConfig,
529 OUT IKsTransport ** OutTransportIn,
530 OUT IKsTransport ** OutTransportOut)
531 {
532 UNIMPLEMENTED
533 return STATUS_NOT_IMPLEMENTED;
534 }
535
536 NTSTATUS
537 NTAPI
538 IKsPin_fnSetTransportConfig(
539 IN IKsPin *iface,
540 IN struct KSPTRANSPORTCONFIG const * TransportConfig,
541 OUT IKsTransport ** OutTransportIn,
542 OUT IKsTransport ** OutTransportOut)
543 {
544 UNIMPLEMENTED
545 return STATUS_NOT_IMPLEMENTED;
546 }
547
548 NTSTATUS
549 NTAPI
550 IKsPin_fnResetTransportConfig(
551 IN IKsPin *iface,
552 OUT IKsTransport ** OutTransportIn,
553 OUT IKsTransport ** OutTransportOut)
554 {
555 UNIMPLEMENTED
556 return STATUS_NOT_IMPLEMENTED;
557 }
558
559 PKSPIN
560 NTAPI
561 IKsPin_fnGetStruct(
562 IN IKsPin *iface)
563 {
564 UNIMPLEMENTED
565 return NULL;
566 }
567
568 PKSPROCESSPIN
569 NTAPI
570 IKsPin_fnGetProcessPin(
571 IN IKsPin *iface)
572 {
573 UNIMPLEMENTED
574 return NULL;
575 }
576
577 NTSTATUS
578 NTAPI
579 IKsPin_fnAttemptBypass(
580 IN IKsPin *iface)
581 {
582 UNIMPLEMENTED
583 return STATUS_NOT_IMPLEMENTED;
584 }
585
586 NTSTATUS
587 NTAPI
588 IKsPin_fnAttemptUnbypass(
589 IN IKsPin *iface)
590 {
591 UNIMPLEMENTED
592 return STATUS_NOT_IMPLEMENTED;
593 }
594
595 VOID
596 NTAPI
597 IKsPin_fnGenerateConnectionEvents(
598 IN IKsPin *iface,
599 IN ULONG EventMask)
600 {
601 UNIMPLEMENTED
602 }
603
604 NTSTATUS
605 NTAPI
606 IKsPin_fnClientSetDeviceState(
607 IN IKsPin *iface,
608 IN KSSTATE StateIn,
609 IN KSSTATE StateOut)
610 {
611 UNIMPLEMENTED
612 return STATUS_NOT_IMPLEMENTED;
613 }
614
615 static IKsPinVtbl vt_IKsPin =
616 {
617 IKsPin_fnQueryInterface,
618 IKsPin_fnAddRef,
619 IKsPin_fnRelease,
620 IKsPin_fnTransferKsIrp,
621 IKsPin_fnDiscardKsIrp,
622 IKsPin_fnConnect,
623 IKsPin_fnSetDeviceState,
624 IKsPin_fnSetResetState,
625 IKsPin_fnGetTransportConfig,
626 IKsPin_fnSetTransportConfig,
627 IKsPin_fnResetTransportConfig,
628 IKsPin_fnGetStruct,
629 IKsPin_fnGetProcessPin,
630 IKsPin_fnAttemptBypass,
631 IKsPin_fnAttemptUnbypass,
632 IKsPin_fnGenerateConnectionEvents,
633 IKsPin_fnClientSetDeviceState
634 };
635
636
637 //==============================================================
638
639 NTSTATUS
640 NTAPI
641 IKsReferenceClock_fnQueryInterface(
642 IKsReferenceClock * iface,
643 IN REFIID refiid,
644 OUT PVOID* Output)
645 {
646 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
647
648 return IKsPin_fnQueryInterface((IKsPin*)&This->lpVtbl, refiid, Output);
649 }
650
651 ULONG
652 NTAPI
653 IKsReferenceClock_fnAddRef(
654 IKsReferenceClock * iface)
655 {
656 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
657
658 return IKsPin_fnAddRef((IKsPin*)&This->lpVtbl);
659 }
660
661 ULONG
662 NTAPI
663 IKsReferenceClock_fnRelease(
664 IKsReferenceClock * iface)
665 {
666 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
667
668 return IKsPin_fnRelease((IKsPin*)&This->lpVtbl);
669 }
670
671 LONGLONG
672 NTAPI
673 IKsReferenceClock_fnGetTime(
674 IKsReferenceClock * iface)
675 {
676 LONGLONG Result;
677
678 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
679
680
681 DPRINT1("IKsReferenceClock_fnGetTime\n");
682
683 if (!This->ClockFileObject || !This->ClockTable.GetTime)
684 {
685 Result = 0;
686 }
687 else
688 {
689 Result = This->ClockTable.GetTime(This->ClockFileObject);
690 }
691
692 return Result;
693 }
694
695 LONGLONG
696 NTAPI
697 IKsReferenceClock_fnGetPhysicalTime(
698 IKsReferenceClock * iface)
699 {
700 LONGLONG Result;
701
702 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
703
704 DPRINT1("IKsReferenceClock_fnGetPhysicalTime\n");
705
706
707 if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime)
708 {
709 Result = 0;
710 }
711 else
712 {
713 Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject);
714 }
715
716 return Result;
717 }
718
719
720 LONGLONG
721 NTAPI
722 IKsReferenceClock_fnGetCorrelatedTime(
723 IKsReferenceClock * iface,
724 OUT PLONGLONG SystemTime)
725 {
726 LONGLONG Result;
727
728 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
729
730 DPRINT1("IKsReferenceClock_fnGetCorrelatedTime\n");
731
732 if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime)
733 {
734 Result = 0;
735 }
736 else
737 {
738 Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime);
739 }
740
741 return Result;
742 }
743
744
745 LONGLONG
746 NTAPI
747 IKsReferenceClock_fnGetCorrelatedPhysicalTime(
748 IKsReferenceClock * iface,
749 OUT PLONGLONG SystemTime)
750 {
751 LONGLONG Result;
752
753 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
754
755 DPRINT1("IKsReferenceClock_fnGetCorrelatedPhysicalTime\n");
756
757 if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime)
758 {
759 Result = 0;
760 }
761 else
762 {
763 Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime);
764 }
765
766 return Result;
767 }
768
769 NTSTATUS
770 NTAPI
771 IKsReferenceClock_fnGetResolution(
772 IKsReferenceClock * iface,
773 OUT PKSRESOLUTION Resolution)
774 {
775 KSPROPERTY Property;
776 ULONG BytesReturned;
777
778 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
779
780 DPRINT1("IKsReferenceClock_fnGetResolution\n");
781
782 if (!This->ClockFileObject)
783 {
784 Resolution->Error = 0;
785 Resolution->Granularity = 1;
786 DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n");
787 return STATUS_SUCCESS;
788 }
789
790
791 if (!This->ClockFileObject)
792 return STATUS_DEVICE_NOT_READY;
793
794
795 Property.Set = KSPROPSETID_Clock;
796 Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
797 Property.Flags = KSPROPERTY_TYPE_GET;
798
799 return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned);
800
801 }
802
803 NTSTATUS
804 NTAPI
805 IKsReferenceClock_fnGetState(
806 IKsReferenceClock * iface,
807 OUT PKSSTATE State)
808 {
809 KSPROPERTY Property;
810 ULONG BytesReturned;
811
812 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
813
814 DPRINT1("IKsReferenceClock_fnGetState\n");
815
816 if (!This->ClockFileObject)
817 {
818 *State = This->Pin.ClientState;
819 DPRINT1("IKsReferenceClock_fnGetState Using HACK\n");
820 return STATUS_SUCCESS;
821 }
822
823
824 if (!This->ClockFileObject)
825 return STATUS_DEVICE_NOT_READY;
826
827
828 Property.Set = KSPROPSETID_Clock;
829 Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
830 Property.Flags = KSPROPERTY_TYPE_GET;
831
832 return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned);
833 }
834
835 static IKsReferenceClockVtbl vt_ReferenceClock =
836 {
837 IKsReferenceClock_fnQueryInterface,
838 IKsReferenceClock_fnAddRef,
839 IKsReferenceClock_fnRelease,
840 IKsReferenceClock_fnGetTime,
841 IKsReferenceClock_fnGetPhysicalTime,
842 IKsReferenceClock_fnGetCorrelatedTime,
843 IKsReferenceClock_fnGetCorrelatedPhysicalTime,
844 IKsReferenceClock_fnGetResolution,
845 IKsReferenceClock_fnGetState
846 };
847
848
849 //==============================================================
850
851
852 /*
853 @implemented
854 */
855 VOID
856 NTAPI
857 KsPinAcquireProcessingMutex(
858 IN PKSPIN Pin)
859 {
860 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
861
862 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
863 }
864
865 /*
866 @implemented
867 */
868 VOID
869 NTAPI
870 KsPinAttachAndGate(
871 IN PKSPIN Pin,
872 IN PKSGATE AndGate OPTIONAL)
873 {
874 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
875
876 /* FIXME attach to filter's and gate (filter-centric processing) */
877
878 This->AttachedGate = AndGate;
879 This->OrGate = FALSE;
880 }
881
882 /*
883 @implemented
884 */
885 VOID
886 NTAPI
887 KsPinAttachOrGate(
888 IN PKSPIN Pin,
889 IN PKSGATE OrGate OPTIONAL)
890 {
891 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
892
893 /* FIXME attach to filter's and gate (filter-centric processing) */
894
895 This->AttachedGate = OrGate;
896 This->OrGate = TRUE;
897 }
898
899 /*
900 @implemented
901 */
902 PKSGATE
903 NTAPI
904 KsPinGetAndGate(
905 IN PKSPIN Pin)
906 {
907 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
908
909 return This->AttachedGate;
910 }
911
912 /*
913 @unimplemented
914 */
915 VOID
916 NTAPI
917 KsPinAttemptProcessing(
918 IN PKSPIN Pin,
919 IN BOOLEAN Asynchronous)
920 {
921 DPRINT("KsPinAttemptProcessing\n");
922 DbgBreakPoint();
923 UNIMPLEMENTED
924 }
925
926 /*
927 @unimplemented
928 */
929 NTSTATUS
930 NTAPI
931 KsPinGetAvailableByteCount(
932 IN PKSPIN Pin,
933 OUT PLONG InputDataBytes OPTIONAL,
934 OUT PLONG OutputBufferBytes OPTIONAL)
935 {
936 UNIMPLEMENTED
937 return STATUS_NOT_IMPLEMENTED;
938 }
939
940 /*
941 @unimplemented
942 */
943 NTSTATUS
944 NTAPI
945 KsPinGetConnectedFilterInterface(
946 IN PKSPIN Pin,
947 IN const GUID* InterfaceId,
948 OUT PVOID* Interface)
949 {
950 UNIMPLEMENTED
951 return STATUS_NOT_IMPLEMENTED;
952 }
953
954 /*
955 @unimplemented
956 */
957 PDEVICE_OBJECT
958 NTAPI
959 KsPinGetConnectedPinDeviceObject(
960 IN PKSPIN Pin)
961 {
962 UNIMPLEMENTED
963 return NULL;
964 }
965
966 /*
967 @unimplemented
968 */
969 PFILE_OBJECT
970 NTAPI
971 KsPinGetConnectedPinFileObject(
972 IN PKSPIN Pin)
973 {
974 UNIMPLEMENTED
975 return NULL;
976 }
977
978 /*
979 @unimplemented
980 */
981 NTSTATUS
982 NTAPI
983 KsPinGetConnectedPinInterface(
984 IN PKSPIN Pin,
985 IN const GUID* InterfaceId,
986 OUT PVOID* Interface)
987 {
988 UNIMPLEMENTED
989 return STATUS_NOT_IMPLEMENTED;
990 }
991
992 /*
993 @unimplemented
994 */
995 VOID
996 NTAPI
997 KsPinGetCopyRelationships(
998 IN PKSPIN Pin,
999 OUT PKSPIN* CopySource,
1000 OUT PKSPIN* DelegateBranch)
1001 {
1002 UNIMPLEMENTED
1003 }
1004
1005 /*
1006 @implemented
1007 */
1008 PKSPIN
1009 NTAPI
1010 KsPinGetNextSiblingPin(
1011 IN PKSPIN Pin)
1012 {
1013 return KsGetNextSibling((PVOID)Pin);
1014 }
1015
1016 /*
1017 @implemented
1018 */
1019 PKSFILTER
1020 NTAPI
1021 KsPinGetParentFilter(
1022 IN PKSPIN Pin)
1023 {
1024 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1025
1026 /* return parent filter */
1027 return This->BasicHeader.Parent.KsFilter;
1028 }
1029
1030 /*
1031 @implemented
1032 */
1033 NTSTATUS
1034 NTAPI
1035 KsPinGetReferenceClockInterface(
1036 IN PKSPIN Pin,
1037 OUT PIKSREFERENCECLOCK* Interface)
1038 {
1039 NTSTATUS Status = STATUS_DEVICE_NOT_READY;
1040 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1041
1042 if (This->ClockFileObject)
1043 {
1044 /* clock is available */
1045 *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
1046 Status = STATUS_SUCCESS;
1047 }
1048 //HACK
1049 *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
1050 Status = STATUS_SUCCESS;
1051
1052 DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status);
1053
1054 return Status;
1055 }
1056
1057 /*
1058 @implemented
1059 */
1060 VOID
1061 NTAPI
1062 KsPinRegisterFrameReturnCallback(
1063 IN PKSPIN Pin,
1064 IN PFNKSPINFRAMERETURN FrameReturn)
1065 {
1066 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1067
1068 /* register frame return callback */
1069 This->FrameReturn = FrameReturn;
1070 }
1071
1072 /*
1073 @implemented
1074 */
1075 VOID
1076 NTAPI
1077 KsPinRegisterHandshakeCallback(
1078 IN PKSPIN Pin,
1079 IN PFNKSPINHANDSHAKE Handshake)
1080 {
1081 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1082
1083 /* register private protocol handshake callback */
1084 This->Handshake = Handshake;
1085 }
1086
1087 /*
1088 @implemented
1089 */
1090 VOID
1091 NTAPI
1092 KsPinRegisterIrpCompletionCallback(
1093 IN PKSPIN Pin,
1094 IN PFNKSPINIRPCOMPLETION IrpCompletion)
1095 {
1096 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1097
1098 /* register irp completion callback */
1099 This->IrpCompletion = IrpCompletion;
1100 }
1101
1102 /*
1103 @implemented
1104 */
1105 VOID
1106 NTAPI
1107 KsPinRegisterPowerCallbacks(
1108 IN PKSPIN Pin,
1109 IN PFNKSPINPOWER Sleep OPTIONAL,
1110 IN PFNKSPINPOWER Wake OPTIONAL)
1111 {
1112 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1113
1114 /* register power callbacks */
1115 This->Sleep = Sleep;
1116 This->Wake = Wake;
1117 }
1118
1119 /*
1120 @implemented
1121 */
1122 VOID
1123 NTAPI
1124 KsPinReleaseProcessingMutex(
1125 IN PKSPIN Pin)
1126 {
1127 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1128
1129 /* release processing mutex */
1130 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1131 }
1132
1133 /*
1134 @implemented
1135 */
1136 KSDDKAPI
1137 PKSPIN
1138 NTAPI
1139 KsGetPinFromIrp(
1140 IN PIRP Irp)
1141 {
1142 PKSIOBJECT_HEADER ObjectHeader;
1143 PKSPIN Pin;
1144 PKSBASIC_HEADER Header;
1145 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
1146
1147 DPRINT("KsGetPinFromIrp\n");
1148
1149 /* get object header */
1150 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1151
1152 if (!ObjectHeader)
1153 return NULL;
1154
1155 Pin = (PKSPIN)ObjectHeader->ObjectType;
1156 Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER));
1157
1158 /* sanity check */
1159 ASSERT(Header->Type == KsObjectTypePin);
1160
1161 /* return object type */
1162 return Pin;
1163 }
1164
1165
1166
1167 /*
1168 @unimplemented
1169 */
1170 VOID
1171 NTAPI
1172 KsPinSetPinClockTime(
1173 IN PKSPIN Pin,
1174 IN LONGLONG Time)
1175 {
1176 UNIMPLEMENTED
1177 }
1178
1179 /*
1180 @unimplemented
1181 */
1182 NTSTATUS
1183 NTAPI
1184 KsPinSubmitFrame(
1185 IN PKSPIN Pin,
1186 IN PVOID Data OPTIONAL,
1187 IN ULONG Size OPTIONAL,
1188 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
1189 IN PVOID Context OPTIONAL)
1190 {
1191 UNIMPLEMENTED
1192 return STATUS_UNSUCCESSFUL;
1193 }
1194
1195 /*
1196 @unimplemented
1197 */
1198 KSDDKAPI
1199 NTSTATUS
1200 NTAPI
1201 KsPinSubmitFrameMdl(
1202 IN PKSPIN Pin,
1203 IN PMDL Mdl OPTIONAL,
1204 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
1205 IN PVOID Context OPTIONAL)
1206 {
1207 UNIMPLEMENTED
1208 return STATUS_UNSUCCESSFUL;
1209 }
1210
1211 /*
1212 @unimplemented
1213 */
1214 KSDDKAPI
1215 BOOLEAN
1216 NTAPI
1217 KsProcessPinUpdate(
1218 IN PKSPROCESSPIN ProcessPin)
1219 {
1220 UNIMPLEMENTED
1221 return FALSE;
1222 }
1223
1224 NTSTATUS
1225 IKsPin_PrepareStreamHeader(
1226 IN IKsPinImpl * This,
1227 IN PKSISTREAM_POINTER StreamPointer)
1228 {
1229 PKSSTREAM_HEADER Header;
1230 ULONG Length;
1231
1232 /* grab new irp */
1233 StreamPointer->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
1234 if (!StreamPointer->Irp)
1235 {
1236 /* run out of mappings */
1237 DPRINT("OutOfMappings\n");
1238 return STATUS_DEVICE_NOT_READY;
1239 }
1240
1241 InterlockedDecrement(&This->IrpCount);
1242 KsDecrementCountedWorker(This->PinWorker);
1243
1244 /* get stream header */
1245 if (StreamPointer->Irp->RequestorMode == UserMode)
1246 Header = (PKSSTREAM_HEADER)StreamPointer->Irp->AssociatedIrp.SystemBuffer;
1247 else
1248 Header = (PKSSTREAM_HEADER)StreamPointer->Irp->UserBuffer;
1249
1250 /* initialize stream pointer */
1251 StreamPointer->Callback = NULL;
1252 StreamPointer->Length = max(Header->DataUsed, Header->FrameExtent);
1253 StreamPointer->Next = NULL;
1254 StreamPointer->Offset = 0;
1255 StreamPointer->Pin = &This->Pin;
1256 StreamPointer->Data = Header->Data;
1257
1258 StreamPointer->StreamPointer.Context = NULL;
1259 StreamPointer->StreamPointer.Pin = &This->Pin;
1260 StreamPointer->StreamPointer.StreamHeader = Header;
1261
1262 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
1263 StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetIn;
1264 else
1265 StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetOut;
1266
1267 StreamPointer->StreamPointer.Offset->Alignment = 0;
1268 StreamPointer->StreamPointer.Offset->Count = 0;
1269 StreamPointer->StreamPointer.Offset->Data = NULL;
1270 StreamPointer->StreamPointer.Offset->Remaining = 0;
1271
1272 ASSERT(StreamPointer->StreamPointer.Offset->Remaining == 0);
1273
1274 //StreamPointer->Offset += StreamPointer->StreamPointer.Offset->Count;
1275
1276 ASSERT(StreamPointer->Length > StreamPointer->Offset);
1277 ASSERT(StreamPointer->StreamPointer.StreamHeader);
1278 ASSERT(This->FrameSize);
1279
1280 /* calculate length */
1281 /* TODO split into frames */
1282 Length = StreamPointer->Length;
1283
1284 /* FIXME */
1285 ASSERT(Length);
1286
1287 StreamPointer->StreamPointer.Offset->Alignment = 0;
1288 StreamPointer->StreamPointer.Context = NULL;
1289 StreamPointer->StreamPointer.Pin = &This->Pin;
1290 StreamPointer->StreamPointer.Offset->Count = Length;
1291 StreamPointer->StreamPointer.Offset->Remaining = Length;
1292 StreamPointer->StreamPointer.Offset->Data = (PVOID)((ULONG_PTR)StreamPointer->Data + StreamPointer->Offset);
1293 StreamPointer->StreamPointer.StreamHeader->FrameExtent = Length;
1294 if (StreamPointer->StreamPointer.StreamHeader->DataUsed)
1295 StreamPointer->StreamPointer.StreamHeader->DataUsed = Length;
1296
1297 StreamPointer->StreamPointer.StreamHeader->Data = StreamPointer->StreamPointer.Offset->Data;
1298
1299 return STATUS_SUCCESS;
1300 }
1301
1302
1303 /*
1304 @unimplemented
1305 */
1306 KSDDKAPI
1307 PKSSTREAM_POINTER
1308 NTAPI
1309 KsPinGetLeadingEdgeStreamPointer(
1310 IN PKSPIN Pin,
1311 IN KSSTREAM_POINTER_STATE State)
1312 {
1313 IKsPinImpl * This;
1314 NTSTATUS Status;
1315
1316 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1317
1318 DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State,
1319 This->LeadingEdgeStreamPointer.Length,
1320 This->LeadingEdgeStreamPointer.Offset);
1321
1322 /* sanity check */
1323 ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED);
1324
1325 if (State == KSSTREAM_POINTER_STATE_LOCKED)
1326 {
1327 if (!This->LeadingEdgeStreamPointer.Irp || This->LeadingEdgeStreamPointer.StreamPointer.Offset->Remaining == 0)
1328 {
1329 Status = IKsPin_PrepareStreamHeader(This, &This->LeadingEdgeStreamPointer);
1330 if (!NT_SUCCESS(Status))
1331 return NULL;
1332 }
1333
1334 DPRINT("KsPinGetLeadingEdgeStreamPointer NewOffset %lu TotalLength %lu\n", This->LeadingEdgeStreamPointer.Offset, This->LeadingEdgeStreamPointer.Length);
1335 }
1336
1337 return &This->LeadingEdgeStreamPointer.StreamPointer;
1338 }
1339
1340 /*
1341 @unimplemented
1342 */
1343 KSDDKAPI
1344 PKSSTREAM_POINTER
1345 NTAPI
1346 KsPinGetTrailingEdgeStreamPointer(
1347 IN PKSPIN Pin,
1348 IN KSSTREAM_POINTER_STATE State)
1349 {
1350 UNIMPLEMENTED
1351 return NULL;
1352 }
1353
1354 /*
1355 @unimplemented
1356 */
1357 KSDDKAPI
1358 NTSTATUS
1359 NTAPI
1360 KsStreamPointerSetStatusCode(
1361 IN PKSSTREAM_POINTER StreamPointer,
1362 IN NTSTATUS Status)
1363 {
1364 UNIMPLEMENTED
1365 return STATUS_UNSUCCESSFUL;
1366 }
1367
1368 /*
1369 @unimplemented
1370 */
1371 KSDDKAPI
1372 NTSTATUS
1373 NTAPI
1374 KsStreamPointerLock(
1375 IN PKSSTREAM_POINTER StreamPointer)
1376 {
1377 UNIMPLEMENTED
1378 return STATUS_UNSUCCESSFUL;
1379 }
1380
1381 /*
1382 @unimplemented
1383 */
1384 KSDDKAPI
1385 VOID
1386 NTAPI
1387 KsStreamPointerUnlock(
1388 IN PKSSTREAM_POINTER StreamPointer,
1389 IN BOOLEAN Eject)
1390 {
1391 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1392
1393 DPRINT("KsStreamPointerUnlock StreamPointer %pEject %lu\n", StreamPointer, Eject);
1394
1395 Pointer->Irp = NULL;
1396 }
1397
1398 /*
1399 @unimplemented
1400 */
1401 KSDDKAPI
1402 VOID
1403 NTAPI
1404 KsStreamPointerAdvanceOffsetsAndUnlock(
1405 IN PKSSTREAM_POINTER StreamPointer,
1406 IN ULONG InUsed,
1407 IN ULONG OutUsed,
1408 IN BOOLEAN Eject)
1409 {
1410 DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
1411 DbgBreakPoint();
1412 UNIMPLEMENTED
1413 }
1414
1415 /*
1416 @implemented
1417 */
1418 KSDDKAPI
1419 VOID
1420 NTAPI
1421 KsStreamPointerDelete(
1422 IN PKSSTREAM_POINTER StreamPointer)
1423 {
1424 IKsPinImpl * This;
1425 PKSISTREAM_POINTER Cur, Last;
1426 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1427
1428 DPRINT("KsStreamPointerDelete %p\n", Pointer);
1429 DbgBreakPoint();
1430 This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
1431
1432 /* point to first stream pointer */
1433 Last = NULL;
1434 Cur = This->ClonedStreamPointer;
1435
1436 while(Cur != Pointer && Cur)
1437 {
1438 Last = Cur;
1439 /* iterate to next cloned pointer */
1440 Cur = Cur->Next;
1441 }
1442
1443 if (!Cur)
1444 {
1445 /* you naughty driver */
1446 return;
1447 }
1448
1449 if (!Last)
1450 {
1451 /* remove first cloned pointer */
1452 This->ClonedStreamPointer = Pointer->Next;
1453 }
1454 else
1455 {
1456 Last->Next = Pointer->Next;
1457 }
1458
1459 /* FIXME make sure no timeouts are pending */
1460 FreeItem(Pointer);
1461 }
1462
1463 /*
1464 @implemented
1465 */
1466 KSDDKAPI
1467 NTSTATUS
1468 NTAPI
1469 KsStreamPointerClone(
1470 IN PKSSTREAM_POINTER StreamPointer,
1471 IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
1472 IN ULONG ContextSize,
1473 OUT PKSSTREAM_POINTER* CloneStreamPointer)
1474 {
1475 IKsPinImpl * This;
1476 PKSISTREAM_POINTER CurFrame;
1477 PKSISTREAM_POINTER NewFrame;
1478 ULONG RefCount;
1479 NTSTATUS Status;
1480 ULONG Size;
1481
1482 DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer);
1483
1484 /* get stream pointer */
1485 CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1486
1487 /* calculate context size */
1488 Size = sizeof(KSISTREAM_POINTER) + ContextSize;
1489
1490 /* allocate new stream pointer */
1491 NewFrame = (PKSISTREAM_POINTER)ExAllocatePool(NonPagedPool, Size);
1492
1493 if (!NewFrame)
1494 return STATUS_INSUFFICIENT_RESOURCES;
1495
1496 /* get current irp stack location */
1497 RefCount = (ULONG)CurFrame->Irp->Tail.Overlay.DriverContext[0];
1498
1499 /* increment reference count */
1500 RefCount++;
1501 CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
1502
1503 /* copy stream pointer */
1504 RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER));
1505
1506 /* locate pin */
1507 This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
1508
1509 /* prepare stream header in case required */
1510 if (CurFrame->StreamPointer.Offset->Remaining == 0)
1511 {
1512 Status = IKsPin_PrepareStreamHeader(This, NewFrame);
1513 if (!NT_SUCCESS(Status))
1514 {
1515 FreeItem(NewFrame);
1516 return STATUS_DEVICE_NOT_READY;
1517 }
1518 }
1519
1520 if (ContextSize)
1521 NewFrame->StreamPointer.Context = (NewFrame + 1);
1522
1523
1524 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
1525 NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetIn;
1526 else
1527 NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetOut;
1528
1529
1530
1531 NewFrame->StreamPointer.Pin = &This->Pin;
1532
1533 ASSERT(NewFrame->StreamPointer.Pin);
1534 ASSERT(NewFrame->StreamPointer.Context);
1535 ASSERT(NewFrame->StreamPointer.Offset);
1536 ASSERT(NewFrame->StreamPointer.StreamHeader);
1537
1538 /* store result */
1539 *CloneStreamPointer = &NewFrame->StreamPointer;
1540
1541 DPRINT("KsStreamPointerClone CloneStreamPointer %p\n", *CloneStreamPointer);
1542
1543 return STATUS_SUCCESS;
1544 }
1545
1546 /*
1547 @implemented
1548 */
1549 KSDDKAPI
1550 NTSTATUS
1551 NTAPI
1552 KsStreamPointerAdvanceOffsets(
1553 IN PKSSTREAM_POINTER StreamPointer,
1554 IN ULONG InUsed,
1555 IN ULONG OutUsed,
1556 IN BOOLEAN Eject)
1557 {
1558 PKSISTREAM_POINTER CurFrame;
1559 IKsPinImpl * This;
1560 NTSTATUS Status;
1561
1562 DPRINT("KsStreamPointerAdvanceOffsets StreamPointer %p InUsed %lu OutUsed %lu Eject %lu\n", StreamPointer, InUsed, OutUsed, Eject);
1563
1564 /* get stream pointer */
1565 CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1566
1567 /* locate pin */
1568 This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
1569
1570 /* TODO */
1571 ASSERT(InUsed == 0);
1572 ASSERT(Eject == 0);
1573 ASSERT(OutUsed);
1574
1575 DPRINT("KsStreamPointerAdvanceOffsets Offset %lu Length %lu NewOffset %lu Remaining %lu LeadingEdge %p DataUsed %lu\n", CurFrame->Offset, CurFrame->Length, CurFrame->Offset + OutUsed,
1576 CurFrame->StreamPointer.OffsetOut.Remaining, &This->LeadingEdgeStreamPointer.StreamPointer, CurFrame->StreamPointer.StreamHeader->DataUsed);
1577 DbgBreakPoint();
1578
1579 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
1580 {
1581 ASSERT(CurFrame->StreamPointer.OffsetIn.Remaining >= InUsed);
1582 CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed;
1583 CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed);
1584 }
1585 else
1586 {
1587 if (!CurFrame->StreamPointer.OffsetOut.Remaining)
1588 {
1589 Status = IKsPin_PrepareStreamHeader(This, CurFrame);
1590 if (!NT_SUCCESS(Status))
1591 {
1592 return STATUS_DEVICE_NOT_READY;
1593 }
1594 }
1595 else
1596 {
1597 ASSERT(CurFrame->StreamPointer.OffsetOut.Remaining >= OutUsed);
1598 CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed;
1599 CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed);
1600 }
1601 }
1602
1603 return STATUS_SUCCESS;
1604 }
1605
1606 /*
1607 @unimplemented
1608 */
1609 KSDDKAPI
1610 NTSTATUS
1611 NTAPI
1612 KsStreamPointerAdvance(
1613 IN PKSSTREAM_POINTER StreamPointer)
1614 {
1615 UNIMPLEMENTED
1616 DbgBreakPoint();
1617 return STATUS_NOT_IMPLEMENTED;
1618 }
1619
1620 /*
1621 @unimplemented
1622 */
1623 KSDDKAPI
1624 PMDL
1625 NTAPI
1626 KsStreamPointerGetMdl(
1627 IN PKSSTREAM_POINTER StreamPointer)
1628 {
1629 UNIMPLEMENTED
1630 return NULL;
1631 }
1632
1633 /*
1634 @unimplemented
1635 */
1636 KSDDKAPI
1637 PIRP
1638 NTAPI
1639 KsStreamPointerGetIrp(
1640 IN PKSSTREAM_POINTER StreamPointer,
1641 OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
1642 OUT PBOOLEAN LastFrameInIrp OPTIONAL)
1643 {
1644 UNIMPLEMENTED
1645 return NULL;
1646 }
1647
1648 /*
1649 @implemented
1650 */
1651 KSDDKAPI
1652 VOID
1653 NTAPI
1654 KsStreamPointerScheduleTimeout(
1655 IN PKSSTREAM_POINTER StreamPointer,
1656 IN PFNKSSTREAMPOINTER Callback,
1657 IN ULONGLONG Interval)
1658 {
1659 LARGE_INTEGER DueTime;
1660 PKSISTREAM_POINTER Pointer;
1661
1662 /* get stream pointer */
1663 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1664
1665 /* setup timer callback */
1666 Pointer->Callback = Callback;
1667
1668 /* setup expiration */
1669 DueTime.QuadPart = (LONGLONG)Interval;
1670
1671 /* setup the timer */
1672 KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
1673
1674 }
1675
1676 /*
1677 @implemented
1678 */
1679 KSDDKAPI
1680 VOID
1681 NTAPI
1682 KsStreamPointerCancelTimeout(
1683 IN PKSSTREAM_POINTER StreamPointer)
1684 {
1685 PKSISTREAM_POINTER Pointer;
1686
1687 /* get stream pointer */
1688 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1689
1690 KeCancelTimer(&Pointer->Timer);
1691
1692 }
1693
1694 /*
1695 @implemented
1696 */
1697 KSDDKAPI
1698 PKSSTREAM_POINTER
1699 NTAPI
1700 KsPinGetFirstCloneStreamPointer(
1701 IN PKSPIN Pin)
1702 {
1703 IKsPinImpl * This;
1704
1705 DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
1706
1707 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1708
1709 if (!This->ClonedStreamPointer)
1710 return NULL;
1711
1712 /* return first cloned stream pointer */
1713 return &This->ClonedStreamPointer->StreamPointer;
1714 }
1715
1716 /*
1717 @implemented
1718 */
1719 KSDDKAPI
1720 PKSSTREAM_POINTER
1721 NTAPI
1722 KsStreamPointerGetNextClone(
1723 IN PKSSTREAM_POINTER StreamPointer)
1724 {
1725 PKSISTREAM_POINTER Pointer;
1726
1727 DPRINT("KsStreamPointerGetNextClone\n");
1728 DbgBreakPoint();
1729 /* get stream pointer */
1730 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1731
1732 /* is there a another cloned stream pointer */
1733 if (!Pointer->Next)
1734 return NULL;
1735
1736 /* return next stream pointer */
1737 return &Pointer->Next->StreamPointer;
1738 }
1739
1740 VOID
1741 NTAPI
1742 IKsPin_PinCentricWorker(
1743 IN PVOID Parameter)
1744 {
1745 NTSTATUS Status;
1746 IKsPinImpl * This = (IKsPinImpl*)Parameter;
1747
1748 DPRINT("IKsPin_PinCentricWorker\n");
1749
1750 /* sanity checks */
1751 ASSERT(This);
1752 ASSERT(This->Pin.Descriptor);
1753 ASSERT(This->Pin.Descriptor->Dispatch);
1754 ASSERT(This->Pin.Descriptor->Dispatch->Process);
1755 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1756 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
1757 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_GENERATE_MAPPINGS));
1758
1759 do
1760 {
1761 DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n");
1762
1763 Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
1764 DPRINT("IKsPin_PinCentricWorker Status %lx, Offset %lu Length %lu\n", Status,
1765 This->LeadingEdgeStreamPointer.Offset,
1766 This->LeadingEdgeStreamPointer.Length);
1767 break;
1768
1769 }while(This->IrpCount);
1770 }
1771
1772
1773 NTSTATUS
1774 NTAPI
1775 IKsPin_DispatchKsStream(
1776 PDEVICE_OBJECT DeviceObject,
1777 PIRP Irp,
1778 IKsPinImpl * This)
1779 {
1780 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
1781 PKSSTREAM_HEADER Header;
1782 ULONG NumHeaders;
1783 PKSFILTER Filter;
1784 PIO_STACK_LOCATION IoStack;
1785 NTSTATUS Status = STATUS_SUCCESS;
1786
1787 DPRINT("IKsPin_DispatchKsStream\n");
1788
1789 /* FIXME handle reset states */
1790 ASSERT(This->Pin.ResetState == KSRESET_END);
1791
1792 /* get current stack location */
1793 IoStack = IoGetCurrentIrpStackLocation(Irp);
1794
1795 /* probe stream pointer */
1796 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
1797 Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
1798 else
1799 Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
1800
1801 if (!NT_SUCCESS(Status))
1802 {
1803 DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
1804
1805 Irp->IoStatus.Status = Status;
1806 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1807 return Status;
1808 }
1809
1810 if (Irp->RequestorMode == UserMode)
1811 Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
1812 else
1813 Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
1814
1815 if (!Header)
1816 {
1817 DPRINT("NoHeader Canceling Irp %p\n", Irp);
1818 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1819 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1820 return Status;
1821 }
1822
1823 /* calculate num headers */
1824 NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
1825
1826 /* assume headers of same length */
1827 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
1828
1829 /* FIXME support multiple stream headers */
1830 ASSERT(NumHeaders == 1);
1831
1832 if (Irp->RequestorMode == UserMode)
1833 {
1834 /* prepare header */
1835 ASSERT(Irp->MdlAddress);
1836 Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
1837
1838 if (!Header->Data)
1839 {
1840 DPRINT("NoHeader->Data Canceling Irp %p\n", Irp);
1841 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1842 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1843 return Status;
1844 }
1845
1846 }
1847
1848
1849
1850 if (This->Pin.Descriptor->Dispatch->Process)
1851 {
1852 /* it is a pin centric avstream */
1853
1854 /* mark irp as pending */
1855 IoMarkIrpPending(Irp);
1856
1857 /* add irp to cancelable queue */
1858 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1859
1860 /* sanity checks */
1861 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
1862 ASSERT(This->PinWorker);
1863
1864 InterlockedIncrement(&This->IrpCount);
1865
1866 DPRINT("IKsPin_DispatchKsStream IrpCount %lu\n", This->IrpCount);
1867
1868 /* start the processing loop */
1869 KsIncrementCountedWorker(This->PinWorker);
1870
1871 Status = STATUS_PENDING;
1872 }
1873 else
1874 {
1875 /* filter-centric avstream */
1876 ASSERT(This->Filter);
1877
1878 ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
1879 Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
1880
1881 ASSERT(ProcessPinIndex);
1882 ASSERT(Filter);
1883 ASSERT(Filter->Descriptor);
1884 ASSERT(Filter->Descriptor->Dispatch);
1885
1886 if (!Filter->Descriptor->Dispatch->Process)
1887 {
1888 /* invalid device request */
1889 DPRINT("Filter Centric Processing No Process Routine\n");
1890 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1891 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1892 return STATUS_UNSUCCESSFUL;
1893 }
1894
1895 /* mark irp as pending */
1896 IoMarkIrpPending(Irp);
1897
1898 /* add irp to cancelable queue */
1899 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1900
1901 Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
1902
1903 DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
1904
1905 }
1906
1907 return Status;
1908 }
1909
1910
1911 NTSTATUS
1912 IKsPin_DispatchKsProperty(
1913 PDEVICE_OBJECT DeviceObject,
1914 PIRP Irp,
1915 IKsPinImpl * This)
1916 {
1917 NTSTATUS Status;
1918 PKSPROPERTY Property;
1919 PIO_STACK_LOCATION IoStack;
1920 UNICODE_STRING GuidString;
1921 ULONG PropertySetsCount = 0, PropertyItemSize = 0;
1922 const KSPROPERTY_SET* PropertySets = NULL;
1923
1924 /* sanity check */
1925 ASSERT(This->Pin.Descriptor);
1926
1927 /* get current irp stack */
1928 IoStack = IoGetCurrentIrpStackLocation(Irp);
1929
1930
1931 if (This->Pin.Descriptor->AutomationTable)
1932 {
1933 /* use available driver property sets */
1934 PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
1935 PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets;
1936 PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
1937 }
1938
1939
1940 /* try driver provided property sets */
1941 Status = KspPropertyHandler(Irp,
1942 PropertySetsCount,
1943 PropertySets,
1944 NULL,
1945 PropertyItemSize);
1946
1947 if (Status != STATUS_NOT_FOUND)
1948 {
1949 /* property was handled by driver */
1950 if (Status != STATUS_PENDING)
1951 {
1952 Irp->IoStatus.Status = Status;
1953 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1954 }
1955 return Status;
1956 }
1957
1958 /* try our properties */
1959 Status = KspPropertyHandler(Irp,
1960 sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET),
1961 PinPropertySet,
1962 NULL,
1963 0);
1964
1965 if (Status != STATUS_NOT_FOUND)
1966 {
1967 /* property was handled by driver */
1968 if (Status != STATUS_PENDING)
1969 {
1970 Irp->IoStatus.Status = Status;
1971 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1972 }
1973 return Status;
1974 }
1975
1976 /* property was not handled */
1977 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1978
1979 RtlStringFromGUID(&Property->Set, &GuidString);
1980 DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
1981 RtlFreeUnicodeString(&GuidString);
1982
1983 Irp->IoStatus.Status = STATUS_NOT_FOUND;
1984 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1985
1986 return STATUS_NOT_FOUND;
1987
1988 }
1989
1990 NTSTATUS
1991 NTAPI
1992 IKsPin_DispatchDeviceIoControl(
1993 IN PDEVICE_OBJECT DeviceObject,
1994 IN PIRP Irp)
1995 {
1996 PIO_STACK_LOCATION IoStack;
1997 PKSIOBJECT_HEADER ObjectHeader;
1998 IKsPinImpl * This;
1999
2000 /* get current irp stack */
2001 IoStack = IoGetCurrentIrpStackLocation(Irp);
2002
2003 /* sanity check */
2004 ASSERT(IoStack->FileObject);
2005 ASSERT(IoStack->FileObject->FsContext2);
2006
2007 /* get the object header */
2008 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2009
2010 /* locate ks pin implemention from KSPIN offset */
2011 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
2012
2013 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
2014 {
2015 /* handle ks properties */
2016 return IKsPin_DispatchKsProperty(DeviceObject, Irp, This);
2017 }
2018
2019 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM ||
2020 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
2021 {
2022 /* handle ks properties */
2023 return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
2024 }
2025
2026 UNIMPLEMENTED;
2027 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2028 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2029 return STATUS_NOT_IMPLEMENTED;
2030 }
2031
2032 NTSTATUS
2033 NTAPI
2034 IKsPin_Close(
2035 IN PDEVICE_OBJECT DeviceObject,
2036 IN PIRP Irp)
2037 {
2038 PIO_STACK_LOCATION IoStack;
2039 PKSIOBJECT_HEADER ObjectHeader;
2040 IKsPinImpl * This;
2041 NTSTATUS Status = STATUS_SUCCESS;
2042
2043 /* get current irp stack */
2044 IoStack = IoGetCurrentIrpStackLocation(Irp);
2045
2046 /* sanity check */
2047 ASSERT(IoStack->FileObject);
2048 ASSERT(IoStack->FileObject->FsContext2);
2049
2050 /* get the object header */
2051 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2052
2053 /* locate ks pin implemention fro KSPIN offset */
2054 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
2055
2056 /* acquire filter control mutex */
2057 KsFilterAcquireControl(&This->Pin);
2058
2059 if (This->Pin.Descriptor->Dispatch->Close)
2060 {
2061 /* call pin close routine */
2062 Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
2063
2064 if (!NT_SUCCESS(Status))
2065 {
2066 /* abort closing */
2067 Irp->IoStatus.Status = Status;
2068 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2069 return Status;
2070 }
2071
2072 /* FIXME remove pin from filter pin list and decrement reference count */
2073
2074 if (Status != STATUS_PENDING)
2075 {
2076 Irp->IoStatus.Status = Status;
2077 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2078 return Status;
2079 }
2080 }
2081
2082 /* release filter control mutex */
2083 KsFilterReleaseControl(&This->Pin);
2084
2085 return Status;
2086 }
2087
2088 NTSTATUS
2089 NTAPI
2090 IKsPin_DispatchCreateAllocator(
2091 IN PDEVICE_OBJECT DeviceObject,
2092 IN PIRP Irp)
2093 {
2094 UNIMPLEMENTED;
2095
2096 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2097 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2098 return STATUS_NOT_IMPLEMENTED;
2099 }
2100
2101 NTSTATUS
2102 NTAPI
2103 IKsPin_DispatchCreateClock(
2104 IN PDEVICE_OBJECT DeviceObject,
2105 IN PIRP Irp)
2106 {
2107 PKSPIN Pin;
2108 NTSTATUS Status = STATUS_SUCCESS;
2109 IKsPinImpl * This;
2110 KSRESOLUTION Resolution;
2111 PKSRESOLUTION pResolution = NULL;
2112 PKSOBJECT_CREATE_ITEM CreateItem;
2113
2114 DPRINT("IKsPin_DispatchCreateClock\n");
2115
2116 /* get the create item */
2117 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
2118
2119 /* sanity check */
2120 ASSERT(CreateItem);
2121
2122 /* get the pin object */
2123 Pin = (PKSPIN)CreateItem->Context;
2124
2125 /* sanity check */
2126 ASSERT(Pin);
2127
2128 /* locate ks pin implemention fro KSPIN offset */
2129 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
2130
2131 /* sanity check */
2132 ASSERT(This->BasicHeader.Type == KsObjectTypePin);
2133 ASSERT(This->BasicHeader.ControlMutex);
2134
2135 /* acquire control mutex */
2136 KsAcquireControl(Pin);
2137
2138 if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
2139 This->Pin.Descriptor->Dispatch) ||
2140 (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
2141 {
2142 if (!This->DefaultClock)
2143 {
2144 if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
2145 {
2146 if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
2147 {
2148 This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
2149 pResolution = &Resolution;
2150 }
2151
2152 Status = KsAllocateDefaultClockEx(&This->DefaultClock,
2153 (PVOID)&This->Pin,
2154 (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
2155 (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
2156 (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
2157 pResolution,
2158 0);
2159 }
2160 else
2161 {
2162 Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
2163 }
2164 }
2165
2166 if (NT_SUCCESS(Status))
2167 {
2168 Status = KsCreateDefaultClock(Irp, This->DefaultClock);
2169 }
2170 }
2171
2172 DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
2173
2174 /* release control mutex */
2175 KsReleaseControl(Pin);
2176
2177 /* done */
2178 Irp->IoStatus.Status = Status;
2179 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2180 return Status;
2181 }
2182
2183 NTSTATUS
2184 NTAPI
2185 IKsPin_DispatchCreateNode(
2186 IN PDEVICE_OBJECT DeviceObject,
2187 IN PIRP Irp)
2188 {
2189 UNIMPLEMENTED;
2190
2191 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2192 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2193 return STATUS_NOT_IMPLEMENTED;
2194 }
2195
2196 static KSDISPATCH_TABLE PinDispatchTable =
2197 {
2198 IKsPin_DispatchDeviceIoControl,
2199 KsDispatchInvalidDeviceRequest,
2200 KsDispatchInvalidDeviceRequest,
2201 KsDispatchInvalidDeviceRequest,
2202 IKsPin_Close,
2203 KsDispatchQuerySecurity,
2204 KsDispatchSetSecurity,
2205 KsDispatchFastIoDeviceControlFailure,
2206 KsDispatchFastReadFailure,
2207 KsDispatchFastReadFailure
2208 };
2209
2210 NTSTATUS
2211 KspCreatePin(
2212 IN PDEVICE_OBJECT DeviceObject,
2213 IN PIRP Irp,
2214 IN PKSDEVICE KsDevice,
2215 IN IKsFilterFactory * FilterFactory,
2216 IN IKsFilter* Filter,
2217 IN PKSPIN_CONNECT Connect,
2218 IN KSPIN_DESCRIPTOR_EX* Descriptor)
2219 {
2220 IKsPinImpl * This;
2221 PIO_STACK_LOCATION IoStack;
2222 IKsDevice * Device;
2223 PDEVICE_EXTENSION DeviceExtension;
2224 PKSOBJECT_CREATE_ITEM CreateItem;
2225 NTSTATUS Status;
2226 PKSDATAFORMAT DataFormat;
2227 PKSBASIC_HEADER BasicHeader;
2228 ULONG Index;
2229 ULONG FrameSize = 0;
2230 ULONG NumFrames = 0;
2231
2232 /* sanity checks */
2233 ASSERT(Descriptor->Dispatch);
2234
2235 DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
2236
2237 //Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
2238 //Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
2239
2240
2241 if (Descriptor->AllocatorFraming)
2242 {
2243 DPRINT("KspCreatePin Dataflow %lu\n", Descriptor->PinDescriptor.DataFlow);
2244 DPRINT("KspCreatePin CountItems %lu\n", Descriptor->AllocatorFraming->CountItems);
2245 DPRINT("KspCreatePin PinFlags %lx\n", Descriptor->AllocatorFraming->PinFlags);
2246 DPRINT("KspCreatePin OutputCompression RatioNumerator %lu RatioDenominator %lu RatioConstantMargin %lu\n", Descriptor->AllocatorFraming->OutputCompression.RatioNumerator,
2247 Descriptor->AllocatorFraming->OutputCompression.RatioDenominator, Descriptor->AllocatorFraming->OutputCompression.RatioConstantMargin);
2248 DPRINT("KspCreatePin PinWeight %lx\n", Descriptor->AllocatorFraming->PinWeight);
2249
2250 for(Index = 0; Index < Descriptor->AllocatorFraming->CountItems; Index++)
2251 {
2252 DPRINT("KspCreatePin Index %lu MemoryFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryFlags);
2253 DPRINT("KspCreatePin Index %lu BusFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].BusFlags);
2254 DPRINT("KspCreatePin Index %lu Flags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Flags);
2255 DPRINT("KspCreatePin Index %lu Frames %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Frames);
2256 DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment);
2257 DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight);
2258 DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize,
2259 Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize,
2260 Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping);
2261
2262 DPRINT("KspCreatePin Index %lu FramingRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n",
2263 Index,
2264 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize,
2265 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize,
2266 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.Stepping,
2267 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.InPlaceWeight,
2268 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.NotInPlaceWeight);
2269
2270 FrameSize = Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize;
2271 NumFrames = Descriptor->AllocatorFraming->FramingItem[Index].Frames;
2272 }
2273 }
2274
2275 if (!FrameSize)
2276 {
2277 /* default to 50 * 188 (MPEG2 TS packet size) */
2278 FrameSize = 9400;
2279 }
2280
2281 if (!NumFrames)
2282 {
2283 NumFrames = 8;
2284 }
2285
2286 /* get current irp stack */
2287 IoStack = IoGetCurrentIrpStackLocation(Irp);
2288
2289 /* get device extension */
2290 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
2291
2292 /* get ks device interface */
2293 Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
2294
2295 /* first allocate pin ctx */
2296 This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
2297 if (!This)
2298 {
2299 /* not enough memory */
2300 return STATUS_INSUFFICIENT_RESOURCES;
2301 }
2302
2303 /* allocate create item */
2304 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
2305 if (!CreateItem)
2306 {
2307 /* not enough memory */
2308 FreeItem(This);
2309 DPRINT("KspCreatePin OutOfMemory\n");
2310 return STATUS_INSUFFICIENT_RESOURCES;
2311 }
2312
2313 /* initialize basic header */
2314 This->BasicHeader.KsDevice = KsDevice;
2315 This->BasicHeader.Type = KsObjectTypePin;
2316 This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
2317
2318 ASSERT(This->BasicHeader.Parent.KsFilter);
2319
2320 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
2321
2322 This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
2323 ASSERT(This->BasicHeader.ControlMutex);
2324
2325 InitializeListHead(&This->BasicHeader.EventList);
2326 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
2327
2328 /* initialize pin */
2329 This->lpVtbl = &vt_IKsPin;
2330 This->FrameSize = FrameSize;
2331 This->NumFrames = NumFrames;
2332 This->lpVtblReferenceClock = &vt_ReferenceClock;
2333 This->ref = 1;
2334 This->FileObject = IoStack->FileObject;
2335 This->Filter = Filter;
2336 KeInitializeMutex(&This->ProcessingMutex, 0);
2337 InitializeListHead(&This->IrpList);
2338 KeInitializeSpinLock(&This->IrpListLock);
2339
2340 /* allocate object bag */
2341 This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
2342 if (!This->Pin.Bag)
2343 {
2344 /* not enough memory */
2345 FreeItem(This);
2346 FreeItem(CreateItem);
2347 return STATUS_INSUFFICIENT_RESOURCES;
2348 }
2349
2350 /* initialize object bag */
2351 Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
2352
2353 /* get format */
2354 DataFormat = (PKSDATAFORMAT)(Connect + 1);
2355
2356 /* initialize pin descriptor */
2357 This->Pin.Descriptor = Descriptor;
2358 This->Pin.Context = NULL;
2359 This->Pin.Id = Connect->PinId;
2360 This->Pin.Communication = Descriptor->PinDescriptor.Communication;
2361 This->Pin.ConnectionIsExternal = FALSE; //FIXME
2362 RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
2363 RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
2364 RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
2365
2366 /* allocate format */
2367 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
2368 if (!NT_SUCCESS(Status))
2369 {
2370 /* failed to allocate format */
2371 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2372 FreeItem(This);
2373 FreeItem(CreateItem);
2374 return STATUS_INSUFFICIENT_RESOURCES;
2375 }
2376
2377 /* copy format */
2378 RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
2379
2380 This->Pin.AttributeList = NULL; //FIXME
2381 This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
2382 This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
2383 This->Pin.DeviceState = KSSTATE_STOP;
2384 This->Pin.ResetState = KSRESET_END;
2385 This->Pin.ClientState = KSSTATE_STOP;
2386
2387 /* intialize allocator create item */
2388 CreateItem[0].Context = (PVOID)&This->Pin;
2389 CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
2390 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
2391 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
2392
2393 /* intialize clock create item */
2394 CreateItem[1].Context = (PVOID)&This->Pin;
2395 CreateItem[1].Create = IKsPin_DispatchCreateClock;
2396 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
2397 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
2398
2399 /* intialize topology node create item */
2400 CreateItem[2].Context = (PVOID)&This->Pin;
2401 CreateItem[2].Create = IKsPin_DispatchCreateNode;
2402 CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
2403 RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
2404
2405 /* now allocate object header */
2406 Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
2407 if (!NT_SUCCESS(Status))
2408 {
2409 /* failed to create object header */
2410 DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
2411 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2412 FreeItem(This);
2413 FreeItem(CreateItem);
2414
2415 /* return failure code */
2416 return Status;
2417 }
2418
2419 /* add extra info to object header */
2420 This->ObjectHeader->Type = KsObjectTypePin;
2421 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
2422 This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
2423
2424 if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
2425 {
2426 /* the pin is part of filter-centric processing filter
2427 * add process pin to filter
2428 */
2429 This->ProcessPin.BytesAvailable = 0;
2430 This->ProcessPin.BytesUsed = 0;
2431 This->ProcessPin.CopySource = NULL;
2432 This->ProcessPin.Data = NULL;
2433 This->ProcessPin.DelegateBranch = NULL;
2434 This->ProcessPin.Flags = 0;
2435 This->ProcessPin.InPlaceCounterpart = NULL;
2436 This->ProcessPin.Pin = &This->Pin;
2437 This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)&This->LeadingEdgeStreamPointer.StreamPointer;
2438 This->ProcessPin.Terminate = FALSE;
2439
2440 Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
2441 DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
2442
2443 if (!NT_SUCCESS(Status))
2444 {
2445 /* failed to add process pin */
2446 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2447 KsFreeObjectHeader(&This->ObjectHeader);
2448 FreeItem(This);
2449 FreeItem(CreateItem);
2450 /* return failure code */
2451 return Status;
2452 }
2453 }
2454 else if (Descriptor->Dispatch && Descriptor->Dispatch->Process)
2455 {
2456 /* pin centric processing filter */
2457
2458 /* initialize work item */
2459 ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This);
2460
2461 /* allocate counted work item */
2462 Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker);
2463
2464 if (!NT_SUCCESS(Status))
2465 {
2466 DPRINT("Failed to register Worker %lx\n", Status);
2467 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2468 KsFreeObjectHeader(&This->ObjectHeader);
2469 FreeItem(This);
2470 FreeItem(CreateItem);
2471 return Status;
2472 }
2473
2474 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
2475 This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetIn;
2476 else
2477 This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetOut;
2478
2479
2480 KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE);
2481
2482 }
2483
2484 /* FIXME add pin instance to filter instance */
2485
2486
2487 if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
2488 {
2489 Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
2490 DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
2491 }
2492
2493
2494 /* does the driver have a pin dispatch */
2495 if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
2496 {
2497 /* now inform the driver to create a new pin */
2498 Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
2499 DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
2500 }
2501
2502
2503 DPRINT("KspCreatePin Status %lx\n", Status);
2504
2505 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
2506 {
2507 /* failed to create pin, release resources */
2508 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
2509 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2510 FreeItem(This);
2511
2512 /* return failure code */
2513 return Status;
2514 }
2515
2516 return Status;
2517 }