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