f3b535673f7b0d60bc018a2599b0c51e05d0f4d0
[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 #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
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
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 implemention 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
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
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 implemention 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
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 implemention 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
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 implemention 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
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
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
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
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
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
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
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
592 IKsPin_fnSetResetState(
593 IN IKsPin *iface,
594 IN KSRESET ResetState,
595 OUT IKsTransport * * OutTransportOut)
596 {
597 UNIMPLEMENTED
598 }
599
600 NTSTATUS
601 NTAPI
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
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
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
637 IKsPin_fnGetStruct(
638 IN IKsPin *iface)
639 {
640 UNIMPLEMENTED
641 return NULL;
642 }
643
644 PKSPROCESSPIN
645 NTAPI
646 IKsPin_fnGetProcessPin(
647 IN IKsPin *iface)
648 {
649 UNIMPLEMENTED
650 return NULL;
651 }
652
653 NTSTATUS
654 NTAPI
655 IKsPin_fnAttemptBypass(
656 IN IKsPin *iface)
657 {
658 UNIMPLEMENTED
659 return STATUS_NOT_IMPLEMENTED;
660 }
661
662 NTSTATUS
663 NTAPI
664 IKsPin_fnAttemptUnbypass(
665 IN IKsPin *iface)
666 {
667 UNIMPLEMENTED
668 return STATUS_NOT_IMPLEMENTED;
669 }
670
671 VOID
672 NTAPI
673 IKsPin_fnGenerateConnectionEvents(
674 IN IKsPin *iface,
675 IN ULONG EventMask)
676 {
677 UNIMPLEMENTED
678 }
679
680 NTSTATUS
681 NTAPI
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1035 KsPinGetConnectedPinDeviceObject(
1036 IN PKSPIN Pin)
1037 {
1038 UNIMPLEMENTED
1039 return NULL;
1040 }
1041
1042 /*
1043 @unimplemented
1044 */
1045 PFILE_OBJECT
1046 NTAPI
1047 KsPinGetConnectedPinFileObject(
1048 IN PKSPIN Pin)
1049 {
1050 UNIMPLEMENTED
1051 return NULL;
1052 }
1053
1054 /*
1055 @unimplemented
1056 */
1057 NTSTATUS
1058 NTAPI
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
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
1086 KsPinGetNextSiblingPin(
1087 IN PKSPIN Pin)
1088 {
1089 return KsGetNextSibling((PVOID)Pin);
1090 }
1091
1092 /*
1093 @implemented
1094 */
1095 PKSFILTER
1096 NTAPI
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
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
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
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
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
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
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
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
1244 KsPinSetPinClockTime(
1245 IN PKSPIN Pin,
1246 IN LONGLONG Time)
1247 {
1248 UNIMPLEMENTED
1249 }
1250
1251 /*
1252 @unimplemented
1253 */
1254 NTSTATUS
1255 NTAPI
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
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
1289 KsProcessPinUpdate(
1290 IN PKSPROCESSPIN ProcessPin)
1291 {
1292 UNIMPLEMENTED
1293 return FALSE;
1294 }
1295
1296 NTSTATUS
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
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
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
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
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
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 DPRINT("KsStreamPointerUnlock StreamPointer %pEject %lu\n", StreamPointer, Eject);
1470
1471 Pointer->Irp = NULL;
1472 }
1473
1474 /*
1475 @unimplemented
1476 */
1477 KSDDKAPI
1478 VOID
1479 NTAPI
1480 KsStreamPointerAdvanceOffsetsAndUnlock(
1481 IN PKSSTREAM_POINTER StreamPointer,
1482 IN ULONG InUsed,
1483 IN ULONG OutUsed,
1484 IN BOOLEAN Eject)
1485 {
1486 DPRINT("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
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
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
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
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
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
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
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
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
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
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
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
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
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 implemention 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
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 implemention 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
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
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 implemention 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
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
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 /* intialize 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 /* intialize 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 /* intialize 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 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
2640 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2641 FreeItem(This);
2642
2643 /* return failure code */
2644 return Status;
2645 }
2646
2647 return Status;
2648 }