Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[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 #ifndef _WIN64
1336 StreamPointer->StreamPointer.Offset->Alignment = 0;
1337 #endif
1338 StreamPointer->StreamPointer.Offset->Count = 0;
1339 StreamPointer->StreamPointer.Offset->Data = NULL;
1340 StreamPointer->StreamPointer.Offset->Remaining = 0;
1341
1342 ASSERT(StreamPointer->StreamPointer.Offset->Remaining == 0);
1343
1344 //StreamPointer->Offset += StreamPointer->StreamPointer.Offset->Count;
1345
1346 ASSERT(StreamPointer->Length > StreamPointer->Offset);
1347 ASSERT(StreamPointer->StreamPointer.StreamHeader);
1348 ASSERT(This->FrameSize);
1349
1350 /* calculate length */
1351 /* TODO split into frames */
1352 Length = StreamPointer->Length;
1353
1354 /* FIXME */
1355 ASSERT(Length);
1356
1357 #ifndef _WIN64
1358 StreamPointer->StreamPointer.Offset->Alignment = 0;
1359 #endif
1360 StreamPointer->StreamPointer.Context = NULL;
1361 StreamPointer->StreamPointer.Pin = &This->Pin;
1362 StreamPointer->StreamPointer.Offset->Count = Length;
1363 StreamPointer->StreamPointer.Offset->Remaining = Length;
1364 StreamPointer->StreamPointer.Offset->Data = (PVOID)((ULONG_PTR)StreamPointer->Data + StreamPointer->Offset);
1365 StreamPointer->StreamPointer.StreamHeader->FrameExtent = Length;
1366 if (StreamPointer->StreamPointer.StreamHeader->DataUsed)
1367 StreamPointer->StreamPointer.StreamHeader->DataUsed = Length;
1368
1369 StreamPointer->StreamPointer.StreamHeader->Data = StreamPointer->StreamPointer.Offset->Data;
1370
1371 return STATUS_SUCCESS;
1372 }
1373
1374
1375 /*
1376 @unimplemented
1377 */
1378 KSDDKAPI
1379 PKSSTREAM_POINTER
1380 NTAPI
1381 KsPinGetLeadingEdgeStreamPointer(
1382 IN PKSPIN Pin,
1383 IN KSSTREAM_POINTER_STATE State)
1384 {
1385 IKsPinImpl * This;
1386 NTSTATUS Status;
1387
1388 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1389
1390 DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State,
1391 This->LeadingEdgeStreamPointer.Length,
1392 This->LeadingEdgeStreamPointer.Offset);
1393
1394 /* sanity check */
1395 ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED);
1396
1397 if (State == KSSTREAM_POINTER_STATE_LOCKED)
1398 {
1399 if (!This->LeadingEdgeStreamPointer.Irp || This->LeadingEdgeStreamPointer.StreamPointer.Offset->Remaining == 0)
1400 {
1401 Status = IKsPin_PrepareStreamHeader(This, &This->LeadingEdgeStreamPointer);
1402 if (!NT_SUCCESS(Status))
1403 return NULL;
1404 }
1405
1406 DPRINT("KsPinGetLeadingEdgeStreamPointer NewOffset %lu TotalLength %lu\n", This->LeadingEdgeStreamPointer.Offset, This->LeadingEdgeStreamPointer.Length);
1407 }
1408
1409 return &This->LeadingEdgeStreamPointer.StreamPointer;
1410 }
1411
1412 /*
1413 @unimplemented
1414 */
1415 KSDDKAPI
1416 PKSSTREAM_POINTER
1417 NTAPI
1418 KsPinGetTrailingEdgeStreamPointer(
1419 IN PKSPIN Pin,
1420 IN KSSTREAM_POINTER_STATE State)
1421 {
1422 UNIMPLEMENTED
1423 return NULL;
1424 }
1425
1426 /*
1427 @unimplemented
1428 */
1429 KSDDKAPI
1430 NTSTATUS
1431 NTAPI
1432 KsStreamPointerSetStatusCode(
1433 IN PKSSTREAM_POINTER StreamPointer,
1434 IN NTSTATUS Status)
1435 {
1436 UNIMPLEMENTED
1437 return STATUS_UNSUCCESSFUL;
1438 }
1439
1440 /*
1441 @unimplemented
1442 */
1443 KSDDKAPI
1444 NTSTATUS
1445 NTAPI
1446 KsStreamPointerLock(
1447 IN PKSSTREAM_POINTER StreamPointer)
1448 {
1449 UNIMPLEMENTED
1450 return STATUS_UNSUCCESSFUL;
1451 }
1452
1453 /*
1454 @unimplemented
1455 */
1456 KSDDKAPI
1457 VOID
1458 NTAPI
1459 KsStreamPointerUnlock(
1460 IN PKSSTREAM_POINTER StreamPointer,
1461 IN BOOLEAN Eject)
1462 {
1463 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1464
1465 DPRINT("KsStreamPointerUnlock StreamPointer %pEject %lu\n", StreamPointer, Eject);
1466
1467 Pointer->Irp = NULL;
1468 }
1469
1470 /*
1471 @unimplemented
1472 */
1473 KSDDKAPI
1474 VOID
1475 NTAPI
1476 KsStreamPointerAdvanceOffsetsAndUnlock(
1477 IN PKSSTREAM_POINTER StreamPointer,
1478 IN ULONG InUsed,
1479 IN ULONG OutUsed,
1480 IN BOOLEAN Eject)
1481 {
1482 DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
1483 DbgBreakPoint();
1484 UNIMPLEMENTED
1485 }
1486
1487 /*
1488 @implemented
1489 */
1490 KSDDKAPI
1491 VOID
1492 NTAPI
1493 KsStreamPointerDelete(
1494 IN PKSSTREAM_POINTER StreamPointer)
1495 {
1496 IKsPinImpl * This;
1497 PKSISTREAM_POINTER Cur, Last;
1498 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1499
1500 DPRINT("KsStreamPointerDelete %p\n", Pointer);
1501 DbgBreakPoint();
1502 This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
1503
1504 /* point to first stream pointer */
1505 Last = NULL;
1506 Cur = This->ClonedStreamPointer;
1507
1508 while(Cur != Pointer && Cur)
1509 {
1510 Last = Cur;
1511 /* iterate to next cloned pointer */
1512 Cur = Cur->Next;
1513 }
1514
1515 if (!Cur)
1516 {
1517 /* you naughty driver */
1518 return;
1519 }
1520
1521 if (!Last)
1522 {
1523 /* remove first cloned pointer */
1524 This->ClonedStreamPointer = Pointer->Next;
1525 }
1526 else
1527 {
1528 Last->Next = Pointer->Next;
1529 }
1530
1531 /* FIXME make sure no timeouts are pending */
1532 FreeItem(Pointer);
1533 }
1534
1535 /*
1536 @implemented
1537 */
1538 KSDDKAPI
1539 NTSTATUS
1540 NTAPI
1541 KsStreamPointerClone(
1542 IN PKSSTREAM_POINTER StreamPointer,
1543 IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
1544 IN ULONG ContextSize,
1545 OUT PKSSTREAM_POINTER* CloneStreamPointer)
1546 {
1547 IKsPinImpl * This;
1548 PKSISTREAM_POINTER CurFrame;
1549 PKSISTREAM_POINTER NewFrame;
1550 ULONG_PTR RefCount;
1551 NTSTATUS Status;
1552 ULONG Size;
1553
1554 DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer);
1555
1556 /* get stream pointer */
1557 CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1558
1559 /* calculate context size */
1560 Size = sizeof(KSISTREAM_POINTER) + ContextSize;
1561
1562 /* allocate new stream pointer */
1563 NewFrame = (PKSISTREAM_POINTER)AllocateItem(NonPagedPool, Size);
1564
1565 if (!NewFrame)
1566 return STATUS_INSUFFICIENT_RESOURCES;
1567
1568 /* get current irp stack location */
1569 RefCount = (ULONG_PTR)CurFrame->Irp->Tail.Overlay.DriverContext[0];
1570
1571 /* increment reference count */
1572 RefCount++;
1573 CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
1574
1575 /* copy stream pointer */
1576 RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER));
1577
1578 /* locate pin */
1579 This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
1580
1581 /* prepare stream header in case required */
1582 if (CurFrame->StreamPointer.Offset->Remaining == 0)
1583 {
1584 Status = IKsPin_PrepareStreamHeader(This, NewFrame);
1585 if (!NT_SUCCESS(Status))
1586 {
1587 FreeItem(NewFrame);
1588 return STATUS_DEVICE_NOT_READY;
1589 }
1590 }
1591
1592 if (ContextSize)
1593 NewFrame->StreamPointer.Context = (NewFrame + 1);
1594
1595
1596 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
1597 NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetIn;
1598 else
1599 NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetOut;
1600
1601
1602
1603 NewFrame->StreamPointer.Pin = &This->Pin;
1604
1605 ASSERT(NewFrame->StreamPointer.Pin);
1606 ASSERT(NewFrame->StreamPointer.Context);
1607 ASSERT(NewFrame->StreamPointer.Offset);
1608 ASSERT(NewFrame->StreamPointer.StreamHeader);
1609
1610 /* store result */
1611 *CloneStreamPointer = &NewFrame->StreamPointer;
1612
1613 DPRINT("KsStreamPointerClone CloneStreamPointer %p\n", *CloneStreamPointer);
1614
1615 return STATUS_SUCCESS;
1616 }
1617
1618 /*
1619 @implemented
1620 */
1621 KSDDKAPI
1622 NTSTATUS
1623 NTAPI
1624 KsStreamPointerAdvanceOffsets(
1625 IN PKSSTREAM_POINTER StreamPointer,
1626 IN ULONG InUsed,
1627 IN ULONG OutUsed,
1628 IN BOOLEAN Eject)
1629 {
1630 PKSISTREAM_POINTER CurFrame;
1631 IKsPinImpl * This;
1632 NTSTATUS Status;
1633
1634 DPRINT("KsStreamPointerAdvanceOffsets StreamPointer %p InUsed %lu OutUsed %lu Eject %lu\n", StreamPointer, InUsed, OutUsed, Eject);
1635
1636 /* get stream pointer */
1637 CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1638
1639 /* locate pin */
1640 This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
1641
1642 /* TODO */
1643 ASSERT(InUsed == 0);
1644 ASSERT(Eject == 0);
1645 ASSERT(OutUsed);
1646
1647 DPRINT("KsStreamPointerAdvanceOffsets Offset %lu Length %lu NewOffset %lu Remaining %lu LeadingEdge %p DataUsed %lu\n", CurFrame->Offset, CurFrame->Length, CurFrame->Offset + OutUsed,
1648 CurFrame->StreamPointer.OffsetOut.Remaining, &This->LeadingEdgeStreamPointer.StreamPointer, CurFrame->StreamPointer.StreamHeader->DataUsed);
1649 DbgBreakPoint();
1650
1651 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
1652 {
1653 ASSERT(CurFrame->StreamPointer.OffsetIn.Remaining >= InUsed);
1654 CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed;
1655 CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed);
1656 }
1657 else
1658 {
1659 if (!CurFrame->StreamPointer.OffsetOut.Remaining)
1660 {
1661 Status = IKsPin_PrepareStreamHeader(This, CurFrame);
1662 if (!NT_SUCCESS(Status))
1663 {
1664 return STATUS_DEVICE_NOT_READY;
1665 }
1666 }
1667 else
1668 {
1669 ASSERT(CurFrame->StreamPointer.OffsetOut.Remaining >= OutUsed);
1670 CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed;
1671 CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed);
1672 }
1673 }
1674
1675 return STATUS_SUCCESS;
1676 }
1677
1678 /*
1679 @unimplemented
1680 */
1681 KSDDKAPI
1682 NTSTATUS
1683 NTAPI
1684 KsStreamPointerAdvance(
1685 IN PKSSTREAM_POINTER StreamPointer)
1686 {
1687 UNIMPLEMENTED
1688 DbgBreakPoint();
1689 return STATUS_NOT_IMPLEMENTED;
1690 }
1691
1692 /*
1693 @unimplemented
1694 */
1695 KSDDKAPI
1696 PMDL
1697 NTAPI
1698 KsStreamPointerGetMdl(
1699 IN PKSSTREAM_POINTER StreamPointer)
1700 {
1701 UNIMPLEMENTED
1702 return NULL;
1703 }
1704
1705 /*
1706 @unimplemented
1707 */
1708 KSDDKAPI
1709 PIRP
1710 NTAPI
1711 KsStreamPointerGetIrp(
1712 IN PKSSTREAM_POINTER StreamPointer,
1713 OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
1714 OUT PBOOLEAN LastFrameInIrp OPTIONAL)
1715 {
1716 UNIMPLEMENTED
1717 return NULL;
1718 }
1719
1720 /*
1721 @implemented
1722 */
1723 KSDDKAPI
1724 VOID
1725 NTAPI
1726 KsStreamPointerScheduleTimeout(
1727 IN PKSSTREAM_POINTER StreamPointer,
1728 IN PFNKSSTREAMPOINTER Callback,
1729 IN ULONGLONG Interval)
1730 {
1731 LARGE_INTEGER DueTime;
1732 PKSISTREAM_POINTER Pointer;
1733
1734 /* get stream pointer */
1735 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1736
1737 /* setup timer callback */
1738 Pointer->Callback = Callback;
1739
1740 /* setup expiration */
1741 DueTime.QuadPart = (LONGLONG)Interval;
1742
1743 /* setup the timer */
1744 KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
1745
1746 }
1747
1748 /*
1749 @implemented
1750 */
1751 KSDDKAPI
1752 VOID
1753 NTAPI
1754 KsStreamPointerCancelTimeout(
1755 IN PKSSTREAM_POINTER StreamPointer)
1756 {
1757 PKSISTREAM_POINTER Pointer;
1758
1759 /* get stream pointer */
1760 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1761
1762 KeCancelTimer(&Pointer->Timer);
1763
1764 }
1765
1766 /*
1767 @implemented
1768 */
1769 KSDDKAPI
1770 PKSSTREAM_POINTER
1771 NTAPI
1772 KsPinGetFirstCloneStreamPointer(
1773 IN PKSPIN Pin)
1774 {
1775 IKsPinImpl * This;
1776
1777 DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
1778
1779 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1780
1781 if (!This->ClonedStreamPointer)
1782 return NULL;
1783
1784 /* return first cloned stream pointer */
1785 return &This->ClonedStreamPointer->StreamPointer;
1786 }
1787
1788 /*
1789 @implemented
1790 */
1791 KSDDKAPI
1792 PKSSTREAM_POINTER
1793 NTAPI
1794 KsStreamPointerGetNextClone(
1795 IN PKSSTREAM_POINTER StreamPointer)
1796 {
1797 PKSISTREAM_POINTER Pointer;
1798
1799 DPRINT("KsStreamPointerGetNextClone\n");
1800 DbgBreakPoint();
1801 /* get stream pointer */
1802 Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
1803
1804 /* is there a another cloned stream pointer */
1805 if (!Pointer->Next)
1806 return NULL;
1807
1808 /* return next stream pointer */
1809 return &Pointer->Next->StreamPointer;
1810 }
1811
1812 VOID
1813 NTAPI
1814 IKsPin_PinCentricWorker(
1815 IN PVOID Parameter)
1816 {
1817 NTSTATUS Status;
1818 IKsPinImpl * This = (IKsPinImpl*)Parameter;
1819
1820 DPRINT("IKsPin_PinCentricWorker\n");
1821
1822 /* sanity checks */
1823 ASSERT(This);
1824 ASSERT(This->Pin.Descriptor);
1825 ASSERT(This->Pin.Descriptor->Dispatch);
1826 ASSERT(This->Pin.Descriptor->Dispatch->Process);
1827 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1828 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
1829 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_GENERATE_MAPPINGS));
1830
1831 do
1832 {
1833 DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n");
1834
1835 Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
1836 DPRINT("IKsPin_PinCentricWorker Status %lx, Offset %lu Length %lu\n", Status,
1837 This->LeadingEdgeStreamPointer.Offset,
1838 This->LeadingEdgeStreamPointer.Length);
1839 break;
1840
1841 }while(This->IrpCount);
1842 }
1843
1844
1845 NTSTATUS
1846 NTAPI
1847 IKsPin_DispatchKsStream(
1848 PDEVICE_OBJECT DeviceObject,
1849 PIRP Irp,
1850 IKsPinImpl * This)
1851 {
1852 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
1853 PKSSTREAM_HEADER Header;
1854 ULONG NumHeaders;
1855 PKSFILTER Filter;
1856 PIO_STACK_LOCATION IoStack;
1857 NTSTATUS Status = STATUS_SUCCESS;
1858
1859 DPRINT("IKsPin_DispatchKsStream\n");
1860
1861 /* FIXME handle reset states */
1862 ASSERT(This->Pin.ResetState == KSRESET_END);
1863
1864 /* get current stack location */
1865 IoStack = IoGetCurrentIrpStackLocation(Irp);
1866
1867 /* probe stream pointer */
1868 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
1869 Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
1870 else
1871 Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
1872
1873 if (!NT_SUCCESS(Status))
1874 {
1875 DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
1876
1877 Irp->IoStatus.Status = Status;
1878 CompleteRequest(Irp, IO_NO_INCREMENT);
1879 return Status;
1880 }
1881
1882 if (Irp->RequestorMode == UserMode)
1883 Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
1884 else
1885 Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
1886
1887 if (!Header)
1888 {
1889 DPRINT("NoHeader Canceling Irp %p\n", Irp);
1890 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1891 CompleteRequest(Irp, IO_NO_INCREMENT);
1892 return Status;
1893 }
1894
1895 /* calculate num headers */
1896 NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
1897
1898 /* assume headers of same length */
1899 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
1900
1901 /* FIXME support multiple stream headers */
1902 ASSERT(NumHeaders == 1);
1903
1904 if (Irp->RequestorMode == UserMode)
1905 {
1906 /* prepare header */
1907 ASSERT(Irp->MdlAddress);
1908 Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
1909
1910 if (!Header->Data)
1911 {
1912 DPRINT("NoHeader->Data Canceling Irp %p\n", Irp);
1913 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1914 CompleteRequest(Irp, IO_NO_INCREMENT);
1915 return Status;
1916 }
1917
1918 }
1919
1920
1921
1922 if (This->Pin.Descriptor->Dispatch->Process)
1923 {
1924 /* it is a pin centric avstream */
1925
1926 /* mark irp as pending */
1927 IoMarkIrpPending(Irp);
1928
1929 /* add irp to cancelable queue */
1930 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1931
1932 /* sanity checks */
1933 ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
1934 ASSERT(This->PinWorker);
1935
1936 InterlockedIncrement(&This->IrpCount);
1937
1938 DPRINT("IKsPin_DispatchKsStream IrpCount %lu\n", This->IrpCount);
1939
1940 /* start the processing loop */
1941 KsIncrementCountedWorker(This->PinWorker);
1942
1943 Status = STATUS_PENDING;
1944 }
1945 else
1946 {
1947 /* filter-centric avstream */
1948 ASSERT(This->Filter);
1949
1950 ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
1951 Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
1952
1953 ASSERT(ProcessPinIndex);
1954 ASSERT(Filter);
1955 ASSERT(Filter->Descriptor);
1956 ASSERT(Filter->Descriptor->Dispatch);
1957
1958 if (!Filter->Descriptor->Dispatch->Process)
1959 {
1960 /* invalid device request */
1961 DPRINT("Filter Centric Processing No Process Routine\n");
1962 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1963 CompleteRequest(Irp, IO_NO_INCREMENT);
1964 return STATUS_UNSUCCESSFUL;
1965 }
1966
1967 /* mark irp as pending */
1968 IoMarkIrpPending(Irp);
1969
1970 /* add irp to cancelable queue */
1971 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1972
1973 Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
1974
1975 DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
1976
1977 }
1978
1979 return Status;
1980 }
1981
1982 NTSTATUS
1983 NTAPI
1984 IKsPin_DispatchDeviceIoControl(
1985 IN PDEVICE_OBJECT DeviceObject,
1986 IN PIRP Irp)
1987 {
1988 PIO_STACK_LOCATION IoStack;
1989 PKSIOBJECT_HEADER ObjectHeader;
1990 IKsPinImpl * This;
1991 NTSTATUS Status;
1992 UNICODE_STRING GuidString;
1993 PKSPROPERTY Property;
1994 ULONG SetCount = 0;
1995
1996 /* get current irp stack */
1997 IoStack = IoGetCurrentIrpStackLocation(Irp);
1998
1999 /* sanity check */
2000 ASSERT(IoStack->FileObject);
2001 ASSERT(IoStack->FileObject->FsContext2);
2002
2003 /* get the object header */
2004 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2005
2006 /* locate ks pin implemention from KSPIN offset */
2007 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
2008
2009 /* current irp stack */
2010 IoStack = IoGetCurrentIrpStackLocation(Irp);
2011
2012 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM ||
2013 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
2014 {
2015 /* handle ks stream packets */
2016 return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
2017 }
2018
2019 /* get property from input buffer */
2020 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
2021
2022 /* sanity check */
2023 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
2024 ASSERT(This->Pin.Descriptor->AutomationTable);
2025
2026 RtlStringFromGUID(&Property->Set, &GuidString);
2027 DPRINT("IKsPin_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
2028 RtlFreeUnicodeString(&GuidString);
2029
2030
2031 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
2032 {
2033 const KSMETHOD_SET *MethodSet = NULL;
2034 ULONG MethodItemSize = 0;
2035
2036 /* check if the driver supports method sets */
2037 if (This->Pin.Descriptor->AutomationTable->MethodSetsCount)
2038 {
2039 SetCount = This->Pin.Descriptor->AutomationTable->MethodSetsCount;
2040 MethodSet = This->Pin.Descriptor->AutomationTable->MethodSets;
2041 MethodItemSize = This->Pin.Descriptor->AutomationTable->MethodItemSize;
2042 }
2043
2044 /* call method set handler */
2045 Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
2046 }
2047 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
2048 {
2049 const KSPROPERTY_SET *PropertySet = NULL;
2050 ULONG PropertyItemSize = 0;
2051
2052 /* check if the driver supports method sets */
2053 if (This->Pin.Descriptor->AutomationTable->PropertySetsCount)
2054 {
2055 SetCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
2056 PropertySet = This->Pin.Descriptor->AutomationTable->PropertySets;
2057 PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
2058 }
2059
2060 /* needed for our property handlers */
2061 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
2062
2063 /* call property handler */
2064 Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
2065 }
2066 else
2067 {
2068 /* sanity check */
2069 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
2070 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
2071
2072 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
2073 {
2074 /* call enable event handlers */
2075 Status = KspEnableEvent(Irp,
2076 This->Pin.Descriptor->AutomationTable->EventSetsCount,
2077 (PKSEVENT_SET)This->Pin.Descriptor->AutomationTable->EventSets,
2078 &This->BasicHeader.EventList,
2079 KSEVENTS_SPINLOCK,
2080 (PVOID)&This->BasicHeader.EventListLock,
2081 NULL,
2082 This->Pin.Descriptor->AutomationTable->EventItemSize);
2083 }
2084 else
2085 {
2086 /* disable event handler */
2087 Status = KsDisableEvent(Irp, &This->BasicHeader.EventList, KSEVENTS_SPINLOCK, &This->BasicHeader.EventListLock);
2088 }
2089 }
2090
2091 RtlStringFromGUID(&Property->Set, &GuidString);
2092 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);
2093 RtlFreeUnicodeString(&GuidString);
2094
2095 if (Status != STATUS_PENDING)
2096 {
2097 Irp->IoStatus.Status = Status;
2098 CompleteRequest(Irp, IO_NO_INCREMENT);
2099 }
2100
2101 /* done */
2102 return Status;
2103 }
2104
2105 NTSTATUS
2106 NTAPI
2107 IKsPin_Close(
2108 IN PDEVICE_OBJECT DeviceObject,
2109 IN PIRP Irp)
2110 {
2111 PIO_STACK_LOCATION IoStack;
2112 PKSIOBJECT_HEADER ObjectHeader;
2113 IKsPinImpl * This;
2114 NTSTATUS Status = STATUS_SUCCESS;
2115
2116 /* get current irp stack */
2117 IoStack = IoGetCurrentIrpStackLocation(Irp);
2118
2119 /* sanity check */
2120 ASSERT(IoStack->FileObject);
2121 ASSERT(IoStack->FileObject->FsContext2);
2122
2123 /* get the object header */
2124 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2125
2126 /* locate ks pin implemention fro KSPIN offset */
2127 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
2128
2129 if (This->Pin.Descriptor->Dispatch->Close)
2130 {
2131 /* call pin close routine */
2132 Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
2133
2134 if (!NT_SUCCESS(Status))
2135 {
2136 /* abort closing */
2137 Irp->IoStatus.Status = Status;
2138 CompleteRequest(Irp, IO_NO_INCREMENT);
2139 return Status;
2140 }
2141
2142 /* remove pin from filter pin list and decrement reference count */
2143 IKsFilter_RemovePin(This->Filter->lpVtbl->GetStruct(This->Filter), &This->Pin);
2144
2145 if (Status != STATUS_PENDING)
2146 {
2147 Irp->IoStatus.Status = Status;
2148 CompleteRequest(Irp, IO_NO_INCREMENT);
2149 return Status;
2150 }
2151 }
2152
2153 return Status;
2154 }
2155
2156 NTSTATUS
2157 NTAPI
2158 IKsPin_DispatchCreateAllocator(
2159 IN PDEVICE_OBJECT DeviceObject,
2160 IN PIRP Irp)
2161 {
2162 UNIMPLEMENTED;
2163
2164 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2165 CompleteRequest(Irp, IO_NO_INCREMENT);
2166 return STATUS_NOT_IMPLEMENTED;
2167 }
2168
2169 NTSTATUS
2170 NTAPI
2171 IKsPin_DispatchCreateClock(
2172 IN PDEVICE_OBJECT DeviceObject,
2173 IN PIRP Irp)
2174 {
2175 PKSPIN Pin;
2176 NTSTATUS Status = STATUS_SUCCESS;
2177 IKsPinImpl * This;
2178 KSRESOLUTION Resolution;
2179 PKSRESOLUTION pResolution = NULL;
2180 PKSOBJECT_CREATE_ITEM CreateItem;
2181
2182 DPRINT("IKsPin_DispatchCreateClock\n");
2183
2184 /* get the create item */
2185 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
2186
2187 /* sanity check */
2188 ASSERT(CreateItem);
2189
2190 /* get the pin object */
2191 Pin = (PKSPIN)CreateItem->Context;
2192
2193 /* sanity check */
2194 ASSERT(Pin);
2195
2196 /* locate ks pin implemention fro KSPIN offset */
2197 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
2198
2199 /* sanity check */
2200 ASSERT(This->BasicHeader.Type == KsObjectTypePin);
2201 ASSERT(This->BasicHeader.ControlMutex);
2202
2203 /* acquire control mutex */
2204 KsAcquireControl(Pin);
2205
2206 if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
2207 This->Pin.Descriptor->Dispatch) ||
2208 (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
2209 {
2210 if (!This->DefaultClock)
2211 {
2212 if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
2213 {
2214 if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
2215 {
2216 This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
2217 pResolution = &Resolution;
2218 }
2219
2220 Status = KsAllocateDefaultClockEx(&This->DefaultClock,
2221 (PVOID)&This->Pin,
2222 (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
2223 (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
2224 (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
2225 pResolution,
2226 0);
2227 }
2228 else
2229 {
2230 Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
2231 }
2232 }
2233
2234 if (NT_SUCCESS(Status))
2235 {
2236 Status = KsCreateDefaultClock(Irp, This->DefaultClock);
2237 }
2238 }
2239
2240 DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
2241
2242 /* release control mutex */
2243 KsReleaseControl(Pin);
2244
2245 /* done */
2246 Irp->IoStatus.Status = Status;
2247 CompleteRequest(Irp, IO_NO_INCREMENT);
2248 return Status;
2249 }
2250
2251 NTSTATUS
2252 NTAPI
2253 IKsPin_DispatchCreateNode(
2254 IN PDEVICE_OBJECT DeviceObject,
2255 IN PIRP Irp)
2256 {
2257 UNIMPLEMENTED;
2258
2259 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2260 CompleteRequest(Irp, IO_NO_INCREMENT);
2261 return STATUS_NOT_IMPLEMENTED;
2262 }
2263
2264 static KSDISPATCH_TABLE PinDispatchTable =
2265 {
2266 IKsPin_DispatchDeviceIoControl,
2267 KsDispatchInvalidDeviceRequest,
2268 KsDispatchInvalidDeviceRequest,
2269 KsDispatchInvalidDeviceRequest,
2270 IKsPin_Close,
2271 KsDispatchQuerySecurity,
2272 KsDispatchSetSecurity,
2273 KsDispatchFastIoDeviceControlFailure,
2274 KsDispatchFastReadFailure,
2275 KsDispatchFastReadFailure
2276 };
2277
2278 NTSTATUS
2279 KspCreatePin(
2280 IN PDEVICE_OBJECT DeviceObject,
2281 IN PIRP Irp,
2282 IN PKSDEVICE KsDevice,
2283 IN IKsFilterFactory * FilterFactory,
2284 IN IKsFilter* Filter,
2285 IN PKSPIN_CONNECT Connect,
2286 IN KSPIN_DESCRIPTOR_EX* Descriptor)
2287 {
2288 IKsPinImpl * This;
2289 PIO_STACK_LOCATION IoStack;
2290 IKsDevice * Device;
2291 PDEVICE_EXTENSION DeviceExtension;
2292 PKSOBJECT_CREATE_ITEM CreateItem;
2293 NTSTATUS Status;
2294 PKSDATAFORMAT DataFormat;
2295 PKSBASIC_HEADER BasicHeader;
2296 ULONG Index;
2297 ULONG FrameSize = 0;
2298 ULONG NumFrames = 0;
2299 KSAUTOMATION_TABLE AutomationTable;
2300
2301 /* sanity checks */
2302 ASSERT(Descriptor->Dispatch);
2303
2304 DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
2305
2306 //Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
2307 //Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
2308
2309 DPRINT("KspCreatePin Dataflow %lu\n", Descriptor->PinDescriptor.DataFlow);
2310 DPRINT("KspCreatePin Communication %lu\n", Descriptor->PinDescriptor.Communication);
2311 if (Descriptor->AllocatorFraming)
2312 {
2313 DPRINT("KspCreatePin CountItems %lu\n", Descriptor->AllocatorFraming->CountItems);
2314 DPRINT("KspCreatePin PinFlags %lx\n", Descriptor->AllocatorFraming->PinFlags);
2315 DPRINT("KspCreatePin OutputCompression RatioNumerator %lu RatioDenominator %lu RatioConstantMargin %lu\n", Descriptor->AllocatorFraming->OutputCompression.RatioNumerator,
2316 Descriptor->AllocatorFraming->OutputCompression.RatioDenominator, Descriptor->AllocatorFraming->OutputCompression.RatioConstantMargin);
2317 DPRINT("KspCreatePin PinWeight %lx\n", Descriptor->AllocatorFraming->PinWeight);
2318
2319 for(Index = 0; Index < Descriptor->AllocatorFraming->CountItems; Index++)
2320 {
2321 DPRINT("KspCreatePin Index %lu MemoryFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryFlags);
2322 DPRINT("KspCreatePin Index %lu BusFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].BusFlags);
2323 DPRINT("KspCreatePin Index %lu Flags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Flags);
2324 DPRINT("KspCreatePin Index %lu Frames %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Frames);
2325 DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment);
2326 DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight);
2327 DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize,
2328 Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize,
2329 Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping);
2330
2331 DPRINT("KspCreatePin Index %lu FramingRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n",
2332 Index,
2333 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize,
2334 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize,
2335 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.Stepping,
2336 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.InPlaceWeight,
2337 Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.NotInPlaceWeight);
2338
2339 FrameSize = Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize;
2340 NumFrames = Descriptor->AllocatorFraming->FramingItem[Index].Frames;
2341 }
2342 }
2343
2344 for (Index = 0; Index < Descriptor->PinDescriptor.DataRangesCount; Index++)
2345 {
2346 UNICODE_STRING GuidString;
2347 /* convert the guid to string */
2348 RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->MajorFormat, &GuidString);
2349 DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer);
2350 RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &GuidString);
2351 DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer);
2352 RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
2353 DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer);
2354 RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
2355 DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index,
2356 Descriptor->PinDescriptor.DataRanges[Index]->FormatSize, Descriptor->PinDescriptor.DataRanges[Index]->Flags, Descriptor->PinDescriptor.DataRanges[Index]->SampleSize, Descriptor->PinDescriptor.DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT));
2357
2358 if (IsEqualGUIDAligned(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT))
2359 {
2360 PKS_DATARANGE_BDA_TRANSPORT Transport = (PKS_DATARANGE_BDA_TRANSPORT)&Descriptor->PinDescriptor.DataRanges[Index];
2361 DPRINT("KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT AvgTimePerFrame %I64u ulcbPhyiscalFrame %lu ulcbPhyiscalFrameAlignment %lu ulcbPhyiscalPacket %lu\n", Transport->BdaTransportInfo.AvgTimePerFrame, Transport->BdaTransportInfo.ulcbPhyiscalFrame,
2362 Transport->BdaTransportInfo.ulcbPhyiscalFrameAlignment, Transport->BdaTransportInfo.ulcbPhyiscalPacket);
2363 }
2364 }
2365 if (!FrameSize)
2366 {
2367 /* default to 50 * 188 (MPEG2 TS packet size) */
2368 FrameSize = 9400;
2369 }
2370
2371 if (!NumFrames)
2372 {
2373 NumFrames = 8;
2374 }
2375
2376 /* get current irp stack */
2377 IoStack = IoGetCurrentIrpStackLocation(Irp);
2378
2379 /* get device extension */
2380 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
2381
2382 /* get ks device interface */
2383 Device = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
2384
2385 /* first allocate pin ctx */
2386 This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
2387 if (!This)
2388 {
2389 /* not enough memory */
2390 return STATUS_INSUFFICIENT_RESOURCES;
2391 }
2392
2393 /* allocate create item */
2394 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
2395 if (!CreateItem)
2396 {
2397 /* not enough memory */
2398 FreeItem(This);
2399 DPRINT("KspCreatePin OutOfMemory\n");
2400 return STATUS_INSUFFICIENT_RESOURCES;
2401 }
2402
2403 /* initialize basic header */
2404 This->BasicHeader.KsDevice = KsDevice;
2405 This->BasicHeader.Type = KsObjectTypePin;
2406 This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
2407 This->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsPin;
2408 InitializeListHead(&This->BasicHeader.EventList);
2409 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
2410
2411 ASSERT(This->BasicHeader.Parent.KsFilter);
2412
2413 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
2414
2415 This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
2416 ASSERT(This->BasicHeader.ControlMutex);
2417
2418 InitializeListHead(&This->BasicHeader.EventList);
2419 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
2420
2421 /* initialize pin */
2422 This->FrameSize = FrameSize;
2423 This->NumFrames = NumFrames;
2424 This->lpVtblReferenceClock = &vt_ReferenceClock;
2425 This->ref = 1;
2426 This->FileObject = IoStack->FileObject;
2427 This->Filter = Filter;
2428 KeInitializeMutex(&This->ProcessingMutex, 0);
2429 InitializeListHead(&This->IrpList);
2430 KeInitializeSpinLock(&This->IrpListLock);
2431
2432 /* allocate object bag */
2433 This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
2434 if (!This->Pin.Bag)
2435 {
2436 /* not enough memory */
2437 FreeItem(This);
2438 FreeItem(CreateItem);
2439 return STATUS_INSUFFICIENT_RESOURCES;
2440 }
2441
2442 /* initialize object bag */
2443 Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
2444
2445 /* allocate pin descriptor */
2446 This->Pin.Descriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
2447 if (!This->Pin.Descriptor)
2448 {
2449 /* not enough memory */
2450 KsFreeObjectBag(This->Pin.Bag);
2451 FreeItem(This);
2452 FreeItem(CreateItem);
2453 return STATUS_INSUFFICIENT_RESOURCES;
2454 }
2455
2456 /* copy pin descriptor */
2457 RtlMoveMemory((PVOID)This->Pin.Descriptor, Descriptor, sizeof(KSPIN_DESCRIPTOR_EX));
2458
2459 /* initialize automation table */
2460 RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
2461
2462 AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
2463 AutomationTable.PropertySets = PinPropertySet;
2464 AutomationTable.PropertySetsCount = sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET);
2465
2466 /* merge in pin property sets */
2467 Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Pin.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)Descriptor->AutomationTable, &AutomationTable, This->Pin.Bag);
2468
2469 if (!NT_SUCCESS(Status))
2470 {
2471 /* not enough memory */
2472 KsFreeObjectBag(This->Pin.Bag);
2473 FreeItem(This);
2474 FreeItem(CreateItem);
2475 return Status;
2476 }
2477
2478 /* get format */
2479 DataFormat = (PKSDATAFORMAT)(Connect + 1);
2480
2481 /* initialize pin descriptor */
2482 This->Pin.Context = NULL;
2483 This->Pin.Id = Connect->PinId;
2484 This->Pin.Communication = Descriptor->PinDescriptor.Communication;
2485 This->Pin.ConnectionIsExternal = FALSE; //FIXME
2486 RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
2487 RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
2488 RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
2489
2490 /* allocate format */
2491 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
2492 if (!NT_SUCCESS(Status))
2493 {
2494 /* failed to allocate format */
2495 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2496 FreeItem(This);
2497 FreeItem(CreateItem);
2498 return STATUS_INSUFFICIENT_RESOURCES;
2499 }
2500
2501 /* copy format */
2502 RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
2503
2504 This->Pin.AttributeList = NULL; //FIXME
2505 This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
2506 This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
2507 This->Pin.DeviceState = KSSTATE_STOP;
2508 This->Pin.ResetState = KSRESET_END;
2509 This->Pin.ClientState = KSSTATE_STOP;
2510
2511 /* intialize allocator create item */
2512 CreateItem[0].Context = (PVOID)&This->Pin;
2513 CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
2514 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
2515 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
2516
2517 /* intialize clock create item */
2518 CreateItem[1].Context = (PVOID)&This->Pin;
2519 CreateItem[1].Create = IKsPin_DispatchCreateClock;
2520 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
2521 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
2522
2523 /* intialize topology node create item */
2524 CreateItem[2].Context = (PVOID)&This->Pin;
2525 CreateItem[2].Create = IKsPin_DispatchCreateNode;
2526 CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
2527 RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
2528
2529 /* now allocate object header */
2530 Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
2531 if (!NT_SUCCESS(Status))
2532 {
2533 /* failed to create object header */
2534 DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
2535 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2536 FreeItem(This);
2537 FreeItem(CreateItem);
2538
2539 /* return failure code */
2540 return Status;
2541 }
2542
2543 /* add extra info to object header */
2544 This->ObjectHeader->Type = KsObjectTypePin;
2545 This->ObjectHeader->Unknown = (PUNKNOWN)&This->BasicHeader.OuterUnknown;
2546 This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
2547
2548 if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
2549 {
2550 /* the pin is part of filter-centric processing filter
2551 * add process pin to filter
2552 */
2553 This->ProcessPin.BytesAvailable = 0;
2554 This->ProcessPin.BytesUsed = 0;
2555 This->ProcessPin.CopySource = NULL;
2556 This->ProcessPin.Data = NULL;
2557 This->ProcessPin.DelegateBranch = NULL;
2558 This->ProcessPin.Flags = 0;
2559 This->ProcessPin.InPlaceCounterpart = NULL;
2560 This->ProcessPin.Pin = &This->Pin;
2561 This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)&This->LeadingEdgeStreamPointer.StreamPointer;
2562 This->ProcessPin.Terminate = FALSE;
2563
2564 Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
2565 DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
2566
2567 if (!NT_SUCCESS(Status))
2568 {
2569 /* failed to add process pin */
2570 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2571 KsFreeObjectHeader(&This->ObjectHeader);
2572 FreeItem(This);
2573 FreeItem(CreateItem);
2574 /* return failure code */
2575 return Status;
2576 }
2577 }
2578 else if (Descriptor->Dispatch && Descriptor->Dispatch->Process)
2579 {
2580 /* pin centric processing filter */
2581
2582 /* initialize work item */
2583 ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This);
2584
2585 /* allocate counted work item */
2586 Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker);
2587
2588 if (!NT_SUCCESS(Status))
2589 {
2590 DPRINT("Failed to register Worker %lx\n", Status);
2591 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2592 KsFreeObjectHeader(&This->ObjectHeader);
2593 FreeItem(This);
2594 FreeItem(CreateItem);
2595 return Status;
2596 }
2597
2598 if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
2599 This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetIn;
2600 else
2601 This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetOut;
2602
2603
2604 KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE);
2605
2606 }
2607
2608 /* FIXME add pin instance to filter instance */
2609 IKsFilter_AddPin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
2610
2611 if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
2612 {
2613 Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
2614 DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
2615 }
2616
2617
2618 /* does the driver have a pin dispatch */
2619 if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
2620 {
2621 /* now inform the driver to create a new pin */
2622 Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
2623 DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
2624 }
2625
2626
2627 DPRINT("KspCreatePin Status %lx KsDevice %p\n", Status, KsDevice);
2628
2629 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
2630 {
2631 /* failed to create pin, release resources */
2632 IKsFilter_RemovePin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
2633 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
2634 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2635 FreeItem(This);
2636
2637 /* return failure code */
2638 return Status;
2639 }
2640
2641 return Status;
2642 }