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