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