70e17e6607af7e091bfbe1fead7e30482bd856a1
[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 KSSTREAM_POINTER StreamPointer;
15 PFNKSSTREAMPOINTER Callback;
16 PIRP Irp;
17 KTIMER Timer;
18 KDPC TimerDpc;
19 struct _KSISTREAM_POINTER *Next;
20
21 }KSISTREAM_POINTER, *PKSISTREAM_POINTER;
22
23 typedef struct
24 {
25 KSBASIC_HEADER BasicHeader;
26 KSPIN Pin;
27 PKSIOBJECT_HEADER ObjectHeader;
28 KSPROCESSPIN ProcessPin;
29 LIST_ENTRY Entry;
30
31 IKsPinVtbl *lpVtbl;
32 LONG ref;
33
34 IKsFilter * Filter;
35 KMUTEX ProcessingMutex;
36 PFILE_OBJECT FileObject;
37
38 PKSGATE AttachedGate;
39 BOOL OrGate;
40
41 LIST_ENTRY IrpList;
42 KSPIN_LOCK IrpListLock;
43
44 PKSISTREAM_POINTER ClonedStreamPointer;
45 PKSISTREAM_POINTER LeadingEdgeStreamPointer;
46 PKSISTREAM_POINTER TrailingStreamPointer;
47
48 PFNKSPINPOWER Sleep;
49 PFNKSPINPOWER Wake;
50 PFNKSPINHANDSHAKE Handshake;
51 PFNKSPINFRAMERETURN FrameReturn;
52 PFNKSPINIRPCOMPLETION IrpCompletion;
53
54 KSCLOCK_FUNCTIONTABLE ClockTable;
55 PFILE_OBJECT ClockFileObject;
56 IKsReferenceClockVtbl * lpVtblReferenceClock;
57 PKSDEFAULTCLOCK DefaultClock;
58
59 }IKsPinImpl;
60
61 NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
62 NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
63 NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
64 NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
65 NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
66 NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
67
68
69
70 DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler);
71 DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId);
72
73 //TODO
74 // KSPROPSETID_Connection
75 // KSPROPERTY_CONNECTION_ACQUIREORDERING
76 // KSPROPSETID_StreamInterface
77 // KSPROPERTY_STREAMINTERFACE_HEADERSIZE
78
79 KSPROPERTY_SET PinPropertySet[] =
80 {
81 {
82 &KSPROPSETID_Connection,
83 sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM),
84 (const KSPROPERTY_ITEM*)&PinConnectionSet,
85 0,
86 NULL
87 },
88 {
89 &KSPROPSETID_Stream,
90 sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM),
91 (const KSPROPERTY_ITEM*)&PinStreamSet,
92 0,
93 NULL
94 }
95 };
96
97 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
98 const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
99 const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
100
101 NTSTATUS
102 NTAPI
103 IKsPin_PinStreamAllocator(
104 IN PIRP Irp,
105 IN PKSIDENTIFIER Request,
106 IN OUT PVOID Data)
107 {
108 UNIMPLEMENTED
109 return STATUS_NOT_IMPLEMENTED;
110 }
111
112 NTSTATUS
113 NTAPI
114 IKsPin_PinMasterClock(
115 IN PIRP Irp,
116 IN PKSIDENTIFIER Request,
117 IN OUT PVOID Data)
118 {
119 PIO_STACK_LOCATION IoStack;
120 PKSIOBJECT_HEADER ObjectHeader;
121 IKsPinImpl * This;
122 NTSTATUS Status = STATUS_SUCCESS;
123 PHANDLE Handle;
124 PFILE_OBJECT FileObject;
125 KPROCESSOR_MODE Mode;
126 KSPROPERTY Property;
127 ULONG BytesReturned;
128
129 /* get current irp stack */
130 IoStack = IoGetCurrentIrpStackLocation(Irp);
131
132 DPRINT("IKsPin_PinMasterClock\n");
133
134 /* sanity check */
135 ASSERT(IoStack->FileObject);
136 ASSERT(IoStack->FileObject->FsContext2);
137
138 /* get the object header */
139 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
140
141 /* locate ks pin implemention from KSPIN offset */
142 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
143
144 /* acquire control mutex */
145 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
146
147 Handle = (PHANDLE)Data;
148
149 if (Request->Flags & KSPROPERTY_TYPE_GET)
150 {
151 if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
152 This->Pin.Descriptor->Dispatch &&
153 (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
154 {
155 *Handle = NULL;
156 Status = STATUS_SUCCESS;
157 }
158 else
159 {
160 /* no clock available */
161 Status = STATUS_UNSUCCESSFUL;
162 }
163 }
164 else if (Request->Flags & KSPROPERTY_TYPE_SET)
165 {
166 if (This->Pin.ClientState != KSSTATE_STOP)
167 {
168 /* can only set in stopped state */
169 Status = STATUS_INVALID_DEVICE_STATE;
170 }
171 else
172 {
173 if (*Handle)
174 {
175 Mode = ExGetPreviousMode();
176
177 Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
178
179 DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
180 if (NT_SUCCESS(Status))
181 {
182 Property.Set = KSPROPSETID_Clock;
183 Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
184 Property.Flags = KSPROPERTY_TYPE_GET;
185
186 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned);
187
188 DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status);
189
190 if (NT_SUCCESS(Status))
191 {
192 This->ClockFileObject = FileObject;
193 }
194 else
195 {
196 ObDereferenceObject(FileObject);
197 }
198 }
199 }
200 else
201 {
202 /* zeroing clock handle */
203 RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE));
204 Status = STATUS_SUCCESS;
205 if (This->ClockFileObject)
206 {
207 FileObject = This->ClockFileObject;
208 This->ClockFileObject = NULL;
209
210 ObDereferenceObject(This->ClockFileObject);
211 }
212 }
213 }
214 }
215
216 /* release processing mutex */
217 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
218
219 DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
220 return Status;
221 }
222
223
224
225 NTSTATUS
226 NTAPI
227 IKsPin_PinPipeId(
228 IN PIRP Irp,
229 IN PKSIDENTIFIER Request,
230 IN OUT PVOID Data)
231 {
232 UNIMPLEMENTED
233 return STATUS_NOT_IMPLEMENTED;
234 }
235
236
237 NTSTATUS
238 NTAPI
239 IKsPin_PinStatePropertyHandler(
240 IN PIRP Irp,
241 IN PKSIDENTIFIER Request,
242 IN OUT PVOID Data)
243 {
244 PIO_STACK_LOCATION IoStack;
245 PKSIOBJECT_HEADER ObjectHeader;
246 IKsPinImpl * This;
247 NTSTATUS Status = STATUS_SUCCESS;
248 KSSTATE OldState;
249 PKSSTATE NewState;
250
251 /* get current irp stack */
252 IoStack = IoGetCurrentIrpStackLocation(Irp);
253
254 DPRINT("IKsPin_PinStatePropertyHandler\n");
255
256 /* sanity check */
257 ASSERT(IoStack->FileObject);
258 ASSERT(IoStack->FileObject->FsContext2);
259
260 /* get the object header */
261 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
262
263 /* locate ks pin implemention from KSPIN offset */
264 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
265
266 /* acquire control mutex */
267 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
268
269 /* grab state */
270 NewState = (PKSSTATE)Data;
271
272 if (Request->Flags & KSPROPERTY_TYPE_GET)
273 {
274 *NewState = This->Pin.DeviceState;
275 Irp->IoStatus.Information = sizeof(KSSTATE);
276 }
277 else if (Request->Flags & KSPROPERTY_TYPE_SET)
278 {
279 if (This->Pin.Descriptor->Dispatch->SetDeviceState)
280 {
281 /* backup old state */
282 OldState = This->Pin.ClientState;
283
284 /* set new state */
285 This->Pin.ClientState = *NewState;
286
287 /* check if it supported */
288 Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState);
289
290 DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status);
291
292 if (!NT_SUCCESS(Status))
293 {
294 /* revert to old state */
295 This->Pin.ClientState = OldState;
296 DbgBreakPoint();
297 }
298 else
299 {
300 /* update device state */
301 This->Pin.DeviceState = *NewState;
302 }
303 }
304 else
305 {
306 /* just set new state */
307 This->Pin.DeviceState = *NewState;
308 This->Pin.ClientState = *NewState;
309 }
310 }
311
312 /* release processing mutex */
313 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
314
315 DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
316 return Status;
317 }
318
319 NTSTATUS
320 NTAPI
321 IKsPin_PinAllocatorFramingPropertyHandler(
322 IN PIRP Irp,
323 IN PKSIDENTIFIER Request,
324 IN OUT PVOID Data)
325 {
326 UNIMPLEMENTED
327 return STATUS_NOT_IMPLEMENTED;
328 }
329
330 NTSTATUS
331 NTAPI
332 IKsPin_PinDataFormatPropertyHandler(
333 IN PIRP Irp,
334 IN PKSPROPERTY Request,
335 IN OUT PVOID Data)
336 {
337 PIO_STACK_LOCATION IoStack;
338 PKSIOBJECT_HEADER ObjectHeader;
339 IKsPinImpl * This;
340 NTSTATUS Status = STATUS_SUCCESS;
341
342 /* get current irp stack */
343 IoStack = IoGetCurrentIrpStackLocation(Irp);
344
345 DPRINT("IKsPin_PinDataFormatPropertyHandler\n");
346
347 /* sanity check */
348 ASSERT(IoStack->FileObject);
349 ASSERT(IoStack->FileObject->FsContext2);
350
351 /* get the object header */
352 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
353
354 /* locate ks pin implemention from KSPIN offset */
355 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
356
357 /* acquire control mutex */
358 KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
359
360 if (Request->Flags & KSPROPERTY_TYPE_GET)
361 {
362 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize)
363 {
364 /* buffer too small */
365 Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize;
366 Status = STATUS_BUFFER_TOO_SMALL;
367 }
368 else
369 {
370 /* copy format */
371 RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize);
372 }
373 }
374 else if (Request->Flags & KSPROPERTY_TYPE_SET)
375 {
376 /* set format */
377 if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT)
378 {
379 /* format cannot be changed */
380 Status = STATUS_INVALID_DEVICE_REQUEST;
381 }
382 else
383 {
384 /* FIXME check if the format is supported */
385 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0);
386
387 if (NT_SUCCESS(Status))
388 {
389 /* store new format */
390 RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
391 }
392 }
393 }
394
395 /* release processing mutex */
396 KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
397
398 DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status);
399
400 return Status;
401 }
402
403 NTSTATUS
404 NTAPI
405 IKsPin_fnQueryInterface(
406 IKsPin * iface,
407 IN REFIID refiid,
408 OUT PVOID* Output)
409 {
410 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
411
412 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
413 {
414 *Output = &This->lpVtbl;
415 _InterlockedIncrement(&This->ref);
416 return STATUS_SUCCESS;
417 }
418 DbgBreakPoint();
419 return STATUS_UNSUCCESSFUL;
420 }
421
422 ULONG
423 NTAPI
424 IKsPin_fnAddRef(
425 IKsPin * iface)
426 {
427 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
428
429 return InterlockedIncrement(&This->ref);
430 }
431
432 ULONG
433 NTAPI
434 IKsPin_fnRelease(
435 IKsPin * iface)
436 {
437 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtbl);
438
439 InterlockedDecrement(&This->ref);
440
441 if (This->ref == 0)
442 {
443 FreeItem(This);
444 return 0;
445 }
446 /* Return new reference count */
447 return This->ref;
448 }
449
450 NTSTATUS
451 NTAPI
452 IKsPin_fnTransferKsIrp(
453 IN IKsPin *iface,
454 IN PIRP Irp,
455 IN IKsTransport **OutTransport)
456 {
457 UNIMPLEMENTED
458 return STATUS_NOT_IMPLEMENTED;
459 }
460
461 VOID
462 NTAPI
463 IKsPin_fnDiscardKsIrp(
464 IN IKsPin *iface,
465 IN PIRP Irp,
466 IN IKsTransport * *OutTransport)
467 {
468 UNIMPLEMENTED
469 }
470
471
472 NTSTATUS
473 NTAPI
474 IKsPin_fnConnect(
475 IN IKsPin *iface,
476 IN IKsTransport * TransportIn,
477 OUT IKsTransport ** OutTransportIn,
478 OUT IKsTransport * *OutTransportOut,
479 IN KSPIN_DATAFLOW DataFlow)
480 {
481 UNIMPLEMENTED
482 return STATUS_NOT_IMPLEMENTED;
483 }
484
485 NTSTATUS
486 NTAPI
487 IKsPin_fnSetDeviceState(
488 IN IKsPin *iface,
489 IN KSSTATE OldState,
490 IN KSSTATE NewState,
491 IN IKsTransport * *OutTransport)
492 {
493 UNIMPLEMENTED
494 return STATUS_NOT_IMPLEMENTED;
495 }
496
497 VOID
498 NTAPI
499 IKsPin_fnSetResetState(
500 IN IKsPin *iface,
501 IN KSRESET ResetState,
502 OUT IKsTransport * * OutTransportOut)
503 {
504 UNIMPLEMENTED
505 }
506
507 NTSTATUS
508 NTAPI
509 IKsPin_fnGetTransportConfig(
510 IN IKsPin *iface,
511 IN struct KSPTRANSPORTCONFIG * TransportConfig,
512 OUT IKsTransport ** OutTransportIn,
513 OUT IKsTransport ** OutTransportOut)
514 {
515 UNIMPLEMENTED
516 return STATUS_NOT_IMPLEMENTED;
517 }
518
519 NTSTATUS
520 NTAPI
521 IKsPin_fnSetTransportConfig(
522 IN IKsPin *iface,
523 IN struct KSPTRANSPORTCONFIG const * TransportConfig,
524 OUT IKsTransport ** OutTransportIn,
525 OUT IKsTransport ** OutTransportOut)
526 {
527 UNIMPLEMENTED
528 return STATUS_NOT_IMPLEMENTED;
529 }
530
531 NTSTATUS
532 NTAPI
533 IKsPin_fnResetTransportConfig(
534 IN IKsPin *iface,
535 OUT IKsTransport ** OutTransportIn,
536 OUT IKsTransport ** OutTransportOut)
537 {
538 UNIMPLEMENTED
539 return STATUS_NOT_IMPLEMENTED;
540 }
541
542 PKSPIN
543 NTAPI
544 IKsPin_fnGetStruct(
545 IN IKsPin *iface)
546 {
547 UNIMPLEMENTED
548 return NULL;
549 }
550
551 PKSPROCESSPIN
552 NTAPI
553 IKsPin_fnGetProcessPin(
554 IN IKsPin *iface)
555 {
556 UNIMPLEMENTED
557 return NULL;
558 }
559
560 NTSTATUS
561 NTAPI
562 IKsPin_fnAttemptBypass(
563 IN IKsPin *iface)
564 {
565 UNIMPLEMENTED
566 return STATUS_NOT_IMPLEMENTED;
567 }
568
569 NTSTATUS
570 NTAPI
571 IKsPin_fnAttemptUnbypass(
572 IN IKsPin *iface)
573 {
574 UNIMPLEMENTED
575 return STATUS_NOT_IMPLEMENTED;
576 }
577
578 VOID
579 NTAPI
580 IKsPin_fnGenerateConnectionEvents(
581 IN IKsPin *iface,
582 IN ULONG EventMask)
583 {
584 UNIMPLEMENTED
585 }
586
587 NTSTATUS
588 NTAPI
589 IKsPin_fnClientSetDeviceState(
590 IN IKsPin *iface,
591 IN KSSTATE StateIn,
592 IN KSSTATE StateOut)
593 {
594 UNIMPLEMENTED
595 return STATUS_NOT_IMPLEMENTED;
596 }
597
598 static IKsPinVtbl vt_IKsPin =
599 {
600 IKsPin_fnQueryInterface,
601 IKsPin_fnAddRef,
602 IKsPin_fnRelease,
603 IKsPin_fnTransferKsIrp,
604 IKsPin_fnDiscardKsIrp,
605 IKsPin_fnConnect,
606 IKsPin_fnSetDeviceState,
607 IKsPin_fnSetResetState,
608 IKsPin_fnGetTransportConfig,
609 IKsPin_fnSetTransportConfig,
610 IKsPin_fnResetTransportConfig,
611 IKsPin_fnGetStruct,
612 IKsPin_fnGetProcessPin,
613 IKsPin_fnAttemptBypass,
614 IKsPin_fnAttemptUnbypass,
615 IKsPin_fnGenerateConnectionEvents,
616 IKsPin_fnClientSetDeviceState
617 };
618
619
620 //==============================================================
621
622 NTSTATUS
623 NTAPI
624 IKsReferenceClock_fnQueryInterface(
625 IKsReferenceClock * iface,
626 IN REFIID refiid,
627 OUT PVOID* Output)
628 {
629 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
630
631 return IKsPin_fnQueryInterface((IKsPin*)&This->lpVtbl, refiid, Output);
632 }
633
634 ULONG
635 NTAPI
636 IKsReferenceClock_fnAddRef(
637 IKsReferenceClock * iface)
638 {
639 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
640
641 return IKsPin_fnAddRef((IKsPin*)&This->lpVtbl);
642 }
643
644 ULONG
645 NTAPI
646 IKsReferenceClock_fnRelease(
647 IKsReferenceClock * iface)
648 {
649 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
650
651 return IKsPin_fnRelease((IKsPin*)&This->lpVtbl);
652 }
653
654 LONGLONG
655 NTAPI
656 IKsReferenceClock_fnGetTime(
657 IKsReferenceClock * iface)
658 {
659 LONGLONG Result;
660
661 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
662
663 if (!This->ClockFileObject || !This->ClockTable.GetTime)
664 {
665 Result = 0;
666 }
667 else
668 {
669 Result = This->ClockTable.GetTime(This->ClockFileObject);
670 }
671
672 return Result;
673 }
674
675 LONGLONG
676 NTAPI
677 IKsReferenceClock_fnGetPhysicalTime(
678 IKsReferenceClock * iface)
679 {
680 LONGLONG Result;
681
682 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
683
684 if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime)
685 {
686 Result = 0;
687 }
688 else
689 {
690 Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject);
691 }
692
693 return Result;
694 }
695
696
697 LONGLONG
698 NTAPI
699 IKsReferenceClock_fnGetCorrelatedTime(
700 IKsReferenceClock * iface,
701 OUT PLONGLONG SystemTime)
702 {
703 LONGLONG Result;
704
705 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
706
707 if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime)
708 {
709 Result = 0;
710 }
711 else
712 {
713 Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime);
714 }
715
716 return Result;
717 }
718
719
720 LONGLONG
721 NTAPI
722 IKsReferenceClock_fnGetCorrelatedPhysicalTime(
723 IKsReferenceClock * iface,
724 OUT PLONGLONG SystemTime)
725 {
726 LONGLONG Result;
727
728 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
729
730 if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime)
731 {
732 Result = 0;
733 }
734 else
735 {
736 Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime);
737 }
738
739 return Result;
740 }
741
742 NTSTATUS
743 NTAPI
744 IKsReferenceClock_fnGetResolution(
745 IKsReferenceClock * iface,
746 OUT PKSRESOLUTION Resolution)
747 {
748 KSPROPERTY Property;
749 ULONG BytesReturned;
750
751 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
752
753 DPRINT1("IKsReferenceClock_fnGetResolution\n");
754
755 if (!This->ClockFileObject)
756 {
757 Resolution->Error = 0;
758 Resolution->Granularity = 1;
759 DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n");
760 return STATUS_SUCCESS;
761 }
762
763
764 if (!This->ClockFileObject)
765 return STATUS_DEVICE_NOT_READY;
766
767
768 Property.Set = KSPROPSETID_Clock;
769 Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
770 Property.Flags = KSPROPERTY_TYPE_GET;
771
772 return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned);
773
774 }
775
776 NTSTATUS
777 NTAPI
778 IKsReferenceClock_fnGetState(
779 IKsReferenceClock * iface,
780 OUT PKSSTATE State)
781 {
782 KSPROPERTY Property;
783 ULONG BytesReturned;
784
785 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
786
787 DPRINT1("IKsReferenceClock_fnGetState\n");
788
789 if (!This->ClockFileObject)
790 {
791 *State = This->Pin.ClientState;
792 DPRINT1("IKsReferenceClock_fnGetState Using HACK\n");
793 return STATUS_SUCCESS;
794 }
795
796
797 if (!This->ClockFileObject)
798 return STATUS_DEVICE_NOT_READY;
799
800
801 Property.Set = KSPROPSETID_Clock;
802 Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
803 Property.Flags = KSPROPERTY_TYPE_GET;
804
805 return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned);
806 }
807
808 static IKsReferenceClockVtbl vt_ReferenceClock =
809 {
810 IKsReferenceClock_fnQueryInterface,
811 IKsReferenceClock_fnAddRef,
812 IKsReferenceClock_fnRelease,
813 IKsReferenceClock_fnGetTime,
814 IKsReferenceClock_fnGetPhysicalTime,
815 IKsReferenceClock_fnGetCorrelatedTime,
816 IKsReferenceClock_fnGetCorrelatedPhysicalTime,
817 IKsReferenceClock_fnGetResolution,
818 IKsReferenceClock_fnGetState
819 };
820
821
822 //==============================================================
823
824
825 /*
826 @implemented
827 */
828 VOID
829 NTAPI
830 KsPinAcquireProcessingMutex(
831 IN PKSPIN Pin)
832 {
833 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
834
835 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
836 }
837
838 /*
839 @implemented
840 */
841 VOID
842 NTAPI
843 KsPinAttachAndGate(
844 IN PKSPIN Pin,
845 IN PKSGATE AndGate OPTIONAL)
846 {
847 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
848
849 /* FIXME attach to filter's and gate (filter-centric processing) */
850
851 This->AttachedGate = AndGate;
852 This->OrGate = FALSE;
853 }
854
855 /*
856 @implemented
857 */
858 VOID
859 NTAPI
860 KsPinAttachOrGate(
861 IN PKSPIN Pin,
862 IN PKSGATE OrGate OPTIONAL)
863 {
864 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
865
866 /* FIXME attach to filter's and gate (filter-centric processing) */
867
868 This->AttachedGate = OrGate;
869 This->OrGate = TRUE;
870 }
871
872 /*
873 @implemented
874 */
875 PKSGATE
876 NTAPI
877 KsPinGetAndGate(
878 IN PKSPIN Pin)
879 {
880 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
881
882 return This->AttachedGate;
883 }
884
885 /*
886 @unimplemented
887 */
888 VOID
889 NTAPI
890 KsPinAttemptProcessing(
891 IN PKSPIN Pin,
892 IN BOOLEAN Asynchronous)
893 {
894 DPRINT("KsPinAttemptProcessing\n");
895 DbgBreakPoint();
896 UNIMPLEMENTED
897 }
898
899 /*
900 @unimplemented
901 */
902 NTSTATUS
903 NTAPI
904 KsPinGetAvailableByteCount(
905 IN PKSPIN Pin,
906 OUT PLONG InputDataBytes OPTIONAL,
907 OUT PLONG OutputBufferBytes OPTIONAL)
908 {
909 UNIMPLEMENTED
910 return STATUS_NOT_IMPLEMENTED;
911 }
912
913 /*
914 @unimplemented
915 */
916 NTSTATUS
917 NTAPI
918 KsPinGetConnectedFilterInterface(
919 IN PKSPIN Pin,
920 IN const GUID* InterfaceId,
921 OUT PVOID* Interface)
922 {
923 UNIMPLEMENTED
924 return STATUS_NOT_IMPLEMENTED;
925 }
926
927 /*
928 @unimplemented
929 */
930 PDEVICE_OBJECT
931 NTAPI
932 KsPinGetConnectedPinDeviceObject(
933 IN PKSPIN Pin)
934 {
935 UNIMPLEMENTED
936 return NULL;
937 }
938
939 /*
940 @unimplemented
941 */
942 PFILE_OBJECT
943 NTAPI
944 KsPinGetConnectedPinFileObject(
945 IN PKSPIN Pin)
946 {
947 UNIMPLEMENTED
948 return NULL;
949 }
950
951 /*
952 @unimplemented
953 */
954 NTSTATUS
955 NTAPI
956 KsPinGetConnectedPinInterface(
957 IN PKSPIN Pin,
958 IN const GUID* InterfaceId,
959 OUT PVOID* Interface)
960 {
961 UNIMPLEMENTED
962 return STATUS_NOT_IMPLEMENTED;
963 }
964
965 /*
966 @unimplemented
967 */
968 VOID
969 NTAPI
970 KsPinGetCopyRelationships(
971 IN PKSPIN Pin,
972 OUT PKSPIN* CopySource,
973 OUT PKSPIN* DelegateBranch)
974 {
975 UNIMPLEMENTED
976 }
977
978 /*
979 @implemented
980 */
981 PKSPIN
982 NTAPI
983 KsPinGetNextSiblingPin(
984 IN PKSPIN Pin)
985 {
986 return KsGetNextSibling((PVOID)Pin);
987 }
988
989 /*
990 @implemented
991 */
992 PKSFILTER
993 NTAPI
994 KsPinGetParentFilter(
995 IN PKSPIN Pin)
996 {
997 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
998
999 /* return parent filter */
1000 return This->BasicHeader.Parent.KsFilter;
1001 }
1002
1003 /*
1004 @implemented
1005 */
1006 NTSTATUS
1007 NTAPI
1008 KsPinGetReferenceClockInterface(
1009 IN PKSPIN Pin,
1010 OUT PIKSREFERENCECLOCK* Interface)
1011 {
1012 NTSTATUS Status = STATUS_DEVICE_NOT_READY;
1013 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1014
1015 if (This->ClockFileObject)
1016 {
1017 /* clock is available */
1018 *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
1019 Status = STATUS_SUCCESS;
1020 }
1021 //HACK
1022 *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
1023 Status = STATUS_SUCCESS;
1024
1025 DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status);
1026
1027 return Status;
1028 }
1029
1030 /*
1031 @implemented
1032 */
1033 VOID
1034 NTAPI
1035 KsPinRegisterFrameReturnCallback(
1036 IN PKSPIN Pin,
1037 IN PFNKSPINFRAMERETURN FrameReturn)
1038 {
1039 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1040
1041 /* register frame return callback */
1042 This->FrameReturn = FrameReturn;
1043 }
1044
1045 /*
1046 @implemented
1047 */
1048 VOID
1049 NTAPI
1050 KsPinRegisterHandshakeCallback(
1051 IN PKSPIN Pin,
1052 IN PFNKSPINHANDSHAKE Handshake)
1053 {
1054 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1055
1056 /* register private protocol handshake callback */
1057 This->Handshake = Handshake;
1058 }
1059
1060 /*
1061 @implemented
1062 */
1063 VOID
1064 NTAPI
1065 KsPinRegisterIrpCompletionCallback(
1066 IN PKSPIN Pin,
1067 IN PFNKSPINIRPCOMPLETION IrpCompletion)
1068 {
1069 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1070
1071 /* register irp completion callback */
1072 This->IrpCompletion = IrpCompletion;
1073 }
1074
1075 /*
1076 @implemented
1077 */
1078 VOID
1079 NTAPI
1080 KsPinRegisterPowerCallbacks(
1081 IN PKSPIN Pin,
1082 IN PFNKSPINPOWER Sleep OPTIONAL,
1083 IN PFNKSPINPOWER Wake OPTIONAL)
1084 {
1085 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1086
1087 /* register power callbacks */
1088 This->Sleep = Sleep;
1089 This->Wake = Wake;
1090 }
1091
1092 /*
1093 @implemented
1094 */
1095 VOID
1096 NTAPI
1097 KsPinReleaseProcessingMutex(
1098 IN PKSPIN Pin)
1099 {
1100 IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1101
1102 /* release processing mutex */
1103 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1104 }
1105
1106 /*
1107 @implemented
1108 */
1109 KSDDKAPI
1110 PKSPIN
1111 NTAPI
1112 KsGetPinFromIrp(
1113 IN PIRP Irp)
1114 {
1115 PKSIOBJECT_HEADER ObjectHeader;
1116 PKSPIN Pin;
1117 PKSBASIC_HEADER Header;
1118 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
1119
1120 DPRINT("KsGetPinFromIrp\n");
1121
1122 /* get object header */
1123 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1124
1125 if (!ObjectHeader)
1126 return NULL;
1127
1128 Pin = (PKSPIN)ObjectHeader->ObjectType;
1129 Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER));
1130
1131 /* sanity check */
1132 ASSERT(Header->Type == KsObjectTypePin);
1133
1134 /* return object type */
1135 return Pin;
1136 }
1137
1138
1139
1140 /*
1141 @unimplemented
1142 */
1143 VOID
1144 NTAPI
1145 KsPinSetPinClockTime(
1146 IN PKSPIN Pin,
1147 IN LONGLONG Time)
1148 {
1149 UNIMPLEMENTED
1150 }
1151
1152 /*
1153 @unimplemented
1154 */
1155 NTSTATUS
1156 NTAPI
1157 KsPinSubmitFrame(
1158 IN PKSPIN Pin,
1159 IN PVOID Data OPTIONAL,
1160 IN ULONG Size OPTIONAL,
1161 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
1162 IN PVOID Context OPTIONAL)
1163 {
1164 UNIMPLEMENTED
1165 return STATUS_UNSUCCESSFUL;
1166 }
1167
1168 /*
1169 @unimplemented
1170 */
1171 KSDDKAPI
1172 NTSTATUS
1173 NTAPI
1174 KsPinSubmitFrameMdl(
1175 IN PKSPIN Pin,
1176 IN PMDL Mdl OPTIONAL,
1177 IN PKSSTREAM_HEADER StreamHeader OPTIONAL,
1178 IN PVOID Context OPTIONAL)
1179 {
1180 UNIMPLEMENTED
1181 return STATUS_UNSUCCESSFUL;
1182 }
1183
1184 /*
1185 @unimplemented
1186 */
1187 KSDDKAPI
1188 BOOLEAN
1189 NTAPI
1190 KsProcessPinUpdate(
1191 IN PKSPROCESSPIN ProcessPin)
1192 {
1193 UNIMPLEMENTED
1194 return FALSE;
1195 }
1196
1197 /*
1198 @unimplemented
1199 */
1200 KSDDKAPI
1201 PKSSTREAM_POINTER
1202 NTAPI
1203 KsPinGetLeadingEdgeStreamPointer(
1204 IN PKSPIN Pin,
1205 IN KSSTREAM_POINTER_STATE State)
1206 {
1207 UNIMPLEMENTED
1208 DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x\n", Pin, State);
1209 DbgBreakPoint();
1210 return NULL;
1211 }
1212
1213 /*
1214 @unimplemented
1215 */
1216 KSDDKAPI
1217 PKSSTREAM_POINTER
1218 NTAPI
1219 KsPinGetTrailingEdgeStreamPointer(
1220 IN PKSPIN Pin,
1221 IN KSSTREAM_POINTER_STATE State)
1222 {
1223 UNIMPLEMENTED
1224 return NULL;
1225 }
1226
1227 /*
1228 @unimplemented
1229 */
1230 KSDDKAPI
1231 NTSTATUS
1232 NTAPI
1233 KsStreamPointerSetStatusCode(
1234 IN PKSSTREAM_POINTER StreamPointer,
1235 IN NTSTATUS Status)
1236 {
1237 UNIMPLEMENTED
1238 return STATUS_UNSUCCESSFUL;
1239 }
1240
1241 /*
1242 @unimplemented
1243 */
1244 KSDDKAPI
1245 NTSTATUS
1246 NTAPI
1247 KsStreamPointerLock(
1248 IN PKSSTREAM_POINTER StreamPointer)
1249 {
1250 UNIMPLEMENTED
1251 return STATUS_UNSUCCESSFUL;
1252 }
1253
1254 /*
1255 @unimplemented
1256 */
1257 KSDDKAPI
1258 VOID
1259 NTAPI
1260 KsStreamPointerUnlock(
1261 IN PKSSTREAM_POINTER StreamPointer,
1262 IN BOOLEAN Eject)
1263 {
1264 UNIMPLEMENTED
1265 DPRINT("KsStreamPointerUnlock\n");
1266 DbgBreakPoint();
1267 }
1268
1269 /*
1270 @unimplemented
1271 */
1272 KSDDKAPI
1273 VOID
1274 NTAPI
1275 KsStreamPointerAdvanceOffsetsAndUnlock(
1276 IN PKSSTREAM_POINTER StreamPointer,
1277 IN ULONG InUsed,
1278 IN ULONG OutUsed,
1279 IN BOOLEAN Eject)
1280 {
1281 DPRINT("KsStreamPointerAdvanceOffsets\n");
1282 DbgBreakPoint();
1283 UNIMPLEMENTED
1284 }
1285
1286 /*
1287 @implemented
1288 */
1289 KSDDKAPI
1290 VOID
1291 NTAPI
1292 KsStreamPointerDelete(
1293 IN PKSSTREAM_POINTER StreamPointer)
1294 {
1295 IKsPinImpl * This;
1296 PKSISTREAM_POINTER Cur, Last;
1297 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
1298
1299 DPRINT("KsStreamPointerDelete\n");
1300 DbgBreakPoint();
1301 This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
1302
1303 /* point to first stream pointer */
1304 Last = NULL;
1305 Cur = This->ClonedStreamPointer;
1306
1307 while(Cur != Pointer && Cur)
1308 {
1309 Last = Cur;
1310 /* iterate to next cloned pointer */
1311 Cur = Cur->Next;
1312 }
1313
1314 if (!Cur)
1315 {
1316 /* you naughty driver */
1317 return;
1318 }
1319
1320 if (!Last)
1321 {
1322 /* remove first cloned pointer */
1323 This->ClonedStreamPointer = Pointer->Next;
1324 }
1325 else
1326 {
1327 Last->Next = Pointer->Next;
1328 }
1329
1330 /* FIXME make sure no timeouts are pending */
1331 FreeItem(Pointer);
1332 }
1333
1334 /*
1335 @unimplemented
1336 */
1337 KSDDKAPI
1338 NTSTATUS
1339 NTAPI
1340 KsStreamPointerClone(
1341 IN PKSSTREAM_POINTER StreamPointer,
1342 IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
1343 IN ULONG ContextSize,
1344 OUT PKSSTREAM_POINTER* CloneStreamPointer)
1345 {
1346 UNIMPLEMENTED
1347 DPRINT("KsStreamPointerClone\n");
1348 DbgBreakPoint();
1349 return STATUS_NOT_IMPLEMENTED;
1350 }
1351
1352 /*
1353 @unimplemented
1354 */
1355 KSDDKAPI
1356 NTSTATUS
1357 NTAPI
1358 KsStreamPointerAdvanceOffsets(
1359 IN PKSSTREAM_POINTER StreamPointer,
1360 IN ULONG InUsed,
1361 IN ULONG OutUsed,
1362 IN BOOLEAN Eject)
1363 {
1364 UNIMPLEMENTED
1365 return STATUS_NOT_IMPLEMENTED;
1366 }
1367
1368 /*
1369 @unimplemented
1370 */
1371 KSDDKAPI
1372 NTSTATUS
1373 NTAPI
1374 KsStreamPointerAdvance(
1375 IN PKSSTREAM_POINTER StreamPointer)
1376 {
1377 UNIMPLEMENTED
1378 return STATUS_NOT_IMPLEMENTED;
1379 }
1380
1381 /*
1382 @unimplemented
1383 */
1384 KSDDKAPI
1385 PMDL
1386 NTAPI
1387 KsStreamPointerGetMdl(
1388 IN PKSSTREAM_POINTER StreamPointer)
1389 {
1390 UNIMPLEMENTED
1391 return NULL;
1392 }
1393
1394 /*
1395 @unimplemented
1396 */
1397 KSDDKAPI
1398 PIRP
1399 NTAPI
1400 KsStreamPointerGetIrp(
1401 IN PKSSTREAM_POINTER StreamPointer,
1402 OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
1403 OUT PBOOLEAN LastFrameInIrp OPTIONAL)
1404 {
1405 UNIMPLEMENTED
1406 return NULL;
1407 }
1408
1409 /*
1410 @implemented
1411 */
1412 KSDDKAPI
1413 VOID
1414 NTAPI
1415 KsStreamPointerScheduleTimeout(
1416 IN PKSSTREAM_POINTER StreamPointer,
1417 IN PFNKSSTREAMPOINTER Callback,
1418 IN ULONGLONG Interval)
1419 {
1420 LARGE_INTEGER DueTime;
1421 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
1422
1423 /* setup timer callback */
1424 Pointer->Callback = Callback;
1425
1426 /* setup expiration */
1427 DueTime.QuadPart = (LONGLONG)Interval;
1428
1429 /* setup the timer */
1430 KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
1431
1432 }
1433
1434 /*
1435 @implemented
1436 */
1437 KSDDKAPI
1438 VOID
1439 NTAPI
1440 KsStreamPointerCancelTimeout(
1441 IN PKSSTREAM_POINTER StreamPointer)
1442 {
1443 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
1444
1445 KeCancelTimer(&Pointer->Timer);
1446
1447 }
1448
1449 /*
1450 @implemented
1451 */
1452 KSDDKAPI
1453 PKSSTREAM_POINTER
1454 NTAPI
1455 KsPinGetFirstCloneStreamPointer(
1456 IN PKSPIN Pin)
1457 {
1458 IKsPinImpl * This;
1459
1460 DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
1461 DbgBreakPoint();
1462 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1463 /* return first cloned stream pointer */
1464 return &This->ClonedStreamPointer->StreamPointer;
1465 }
1466
1467 /*
1468 @implemented
1469 */
1470 KSDDKAPI
1471 PKSSTREAM_POINTER
1472 NTAPI
1473 KsStreamPointerGetNextClone(
1474 IN PKSSTREAM_POINTER StreamPointer)
1475 {
1476 PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
1477
1478 DPRINT("KsStreamPointerGetNextClone\n");
1479 DbgBreakPoint();
1480 /* is there a another cloned stream pointer */
1481 if (!Pointer->Next)
1482 return NULL;
1483
1484 /* return next stream pointer */
1485 return &Pointer->Next->StreamPointer;
1486 }
1487 NTSTATUS
1488 IKsPin_DispatchKsStream(
1489 PDEVICE_OBJECT DeviceObject,
1490 PIRP Irp,
1491 IKsPinImpl * This)
1492 {
1493 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
1494 PKSFILTER Filter;
1495 NTSTATUS Status = STATUS_SUCCESS;
1496
1497 DPRINT("IKsPin_DispatchKsStream\n");
1498
1499 /* FIXME handle reset states */
1500 ASSERT(This->Pin.ResetState == KSRESET_END);
1501
1502 /* mark irp as pending */
1503 IoMarkIrpPending(Irp);
1504
1505 /* add irp to cancelable queue */
1506 KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
1507
1508 if (This->Pin.Descriptor->Dispatch->Process)
1509 {
1510 /* it is a pin centric avstream */
1511 ASSERT(0);
1512 //Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
1513 /* TODO */
1514 }
1515 else
1516 {
1517 /* filter-centric avstream */
1518 ASSERT(This->Filter);
1519
1520 ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
1521 Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
1522
1523 ASSERT(ProcessPinIndex);
1524 ASSERT(Filter);
1525 ASSERT(Filter->Descriptor);
1526 ASSERT(Filter->Descriptor->Dispatch);
1527
1528 if (!Filter->Descriptor->Dispatch->Process)
1529 {
1530 /* invalid device request */
1531 DPRINT("Filter Centric Processing No Process Routine\n");
1532 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1533 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1534 return STATUS_UNSUCCESSFUL;
1535 }
1536
1537 Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
1538
1539 DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
1540 }
1541
1542 return Status;
1543 }
1544
1545
1546 NTSTATUS
1547 IKsPin_DispatchKsProperty(
1548 PDEVICE_OBJECT DeviceObject,
1549 PIRP Irp,
1550 IKsPinImpl * This)
1551 {
1552 NTSTATUS Status;
1553 PKSPROPERTY Property;
1554 PIO_STACK_LOCATION IoStack;
1555 UNICODE_STRING GuidString;
1556 ULONG PropertySetsCount = 0, PropertyItemSize = 0;
1557 const KSPROPERTY_SET* PropertySets = NULL;
1558
1559 /* sanity check */
1560 ASSERT(This->Pin.Descriptor);
1561
1562 /* get current irp stack */
1563 IoStack = IoGetCurrentIrpStackLocation(Irp);
1564
1565
1566 if (This->Pin.Descriptor->AutomationTable)
1567 {
1568 /* use available driver property sets */
1569 PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
1570 PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets;
1571 PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
1572 }
1573
1574
1575 /* try driver provided property sets */
1576 Status = KspPropertyHandler(Irp,
1577 PropertySetsCount,
1578 PropertySets,
1579 NULL,
1580 PropertyItemSize);
1581
1582 if (Status != STATUS_NOT_FOUND)
1583 {
1584 /* property was handled by driver */
1585 if (Status != STATUS_PENDING)
1586 {
1587 Irp->IoStatus.Status = Status;
1588 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1589 }
1590 return Status;
1591 }
1592
1593 /* try our properties */
1594 Status = KspPropertyHandler(Irp,
1595 sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET),
1596 PinPropertySet,
1597 NULL,
1598 0);
1599
1600 if (Status != STATUS_NOT_FOUND)
1601 {
1602 /* property was handled by driver */
1603 if (Status != STATUS_PENDING)
1604 {
1605 Irp->IoStatus.Status = Status;
1606 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1607 }
1608 return Status;
1609 }
1610
1611 /* property was not handled */
1612 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1613
1614 RtlStringFromGUID(&Property->Set, &GuidString);
1615 DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
1616 RtlFreeUnicodeString(&GuidString);
1617
1618 Irp->IoStatus.Status = STATUS_NOT_FOUND;
1619 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1620
1621 return STATUS_NOT_FOUND;
1622
1623 }
1624
1625 NTSTATUS
1626 NTAPI
1627 IKsPin_DispatchDeviceIoControl(
1628 IN PDEVICE_OBJECT DeviceObject,
1629 IN PIRP Irp)
1630 {
1631 PIO_STACK_LOCATION IoStack;
1632 PKSIOBJECT_HEADER ObjectHeader;
1633 IKsPinImpl * This;
1634
1635 /* get current irp stack */
1636 IoStack = IoGetCurrentIrpStackLocation(Irp);
1637
1638 /* sanity check */
1639 ASSERT(IoStack->FileObject);
1640 ASSERT(IoStack->FileObject->FsContext2);
1641
1642 /* get the object header */
1643 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1644
1645 /* locate ks pin implemention from KSPIN offset */
1646 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
1647
1648 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
1649 {
1650 /* handle ks properties */
1651 return IKsPin_DispatchKsProperty(DeviceObject, Irp, This);
1652 }
1653
1654 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM ||
1655 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
1656 {
1657 /* handle ks properties */
1658 return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
1659 }
1660
1661 UNIMPLEMENTED;
1662 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1663 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1664 return STATUS_NOT_IMPLEMENTED;
1665 }
1666
1667 NTSTATUS
1668 NTAPI
1669 IKsPin_Close(
1670 IN PDEVICE_OBJECT DeviceObject,
1671 IN PIRP Irp)
1672 {
1673 PIO_STACK_LOCATION IoStack;
1674 PKSIOBJECT_HEADER ObjectHeader;
1675 IKsPinImpl * This;
1676 NTSTATUS Status = STATUS_SUCCESS;
1677
1678 /* get current irp stack */
1679 IoStack = IoGetCurrentIrpStackLocation(Irp);
1680
1681 /* sanity check */
1682 ASSERT(IoStack->FileObject);
1683 ASSERT(IoStack->FileObject->FsContext2);
1684
1685 /* get the object header */
1686 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
1687
1688 /* locate ks pin implemention fro KSPIN offset */
1689 This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
1690
1691 /* acquire filter control mutex */
1692 KsFilterAcquireControl(&This->Pin);
1693
1694 if (This->Pin.Descriptor->Dispatch->Close)
1695 {
1696 /* call pin close routine */
1697 Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
1698
1699 if (!NT_SUCCESS(Status))
1700 {
1701 /* abort closing */
1702 Irp->IoStatus.Status = Status;
1703 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1704 return Status;
1705 }
1706
1707 /* FIXME remove pin from filter pin list and decrement reference count */
1708
1709 if (Status != STATUS_PENDING)
1710 {
1711 Irp->IoStatus.Status = Status;
1712 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1713 return Status;
1714 }
1715 }
1716
1717 /* release filter control mutex */
1718 KsFilterReleaseControl(&This->Pin);
1719
1720 return Status;
1721 }
1722
1723 NTSTATUS
1724 NTAPI
1725 IKsPin_DispatchCreateAllocator(
1726 IN PDEVICE_OBJECT DeviceObject,
1727 IN PIRP Irp)
1728 {
1729 UNIMPLEMENTED;
1730
1731 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1732 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1733 return STATUS_NOT_IMPLEMENTED;
1734 }
1735
1736 NTSTATUS
1737 NTAPI
1738 IKsPin_DispatchCreateClock(
1739 IN PDEVICE_OBJECT DeviceObject,
1740 IN PIRP Irp)
1741 {
1742 PKSPIN Pin;
1743 NTSTATUS Status = STATUS_SUCCESS;
1744 IKsPinImpl * This;
1745 KSRESOLUTION Resolution;
1746 PKSRESOLUTION pResolution = NULL;
1747 PKSOBJECT_CREATE_ITEM CreateItem;
1748
1749 DPRINT("IKsPin_DispatchCreateClock\n");
1750
1751 /* get the create item */
1752 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1753
1754 /* sanity check */
1755 ASSERT(CreateItem);
1756
1757 /* get the pin object */
1758 Pin = (PKSPIN)CreateItem->Context;
1759
1760 /* sanity check */
1761 ASSERT(Pin);
1762
1763 /* locate ks pin implemention fro KSPIN offset */
1764 This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
1765
1766 /* sanity check */
1767 ASSERT(This->BasicHeader.Type == KsObjectTypePin);
1768 ASSERT(This->BasicHeader.ControlMutex);
1769
1770 /* acquire control mutex */
1771 KsAcquireControl(Pin);
1772
1773 if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
1774 This->Pin.Descriptor->Dispatch) ||
1775 (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
1776 {
1777 if (!This->DefaultClock)
1778 {
1779 if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
1780 {
1781 if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
1782 {
1783 This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
1784 pResolution = &Resolution;
1785 }
1786
1787 Status = KsAllocateDefaultClockEx(&This->DefaultClock,
1788 (PVOID)&This->Pin,
1789 (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
1790 (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
1791 (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
1792 pResolution,
1793 0);
1794 }
1795 else
1796 {
1797 Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
1798 }
1799 }
1800
1801 if (NT_SUCCESS(Status))
1802 {
1803 Status = KsCreateDefaultClock(Irp, This->DefaultClock);
1804 }
1805 }
1806
1807 DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
1808
1809 /* release control mutex */
1810 KsReleaseControl(Pin);
1811
1812 /* done */
1813 Irp->IoStatus.Status = Status;
1814 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1815 return Status;
1816 }
1817
1818 NTSTATUS
1819 NTAPI
1820 IKsPin_DispatchCreateNode(
1821 IN PDEVICE_OBJECT DeviceObject,
1822 IN PIRP Irp)
1823 {
1824 UNIMPLEMENTED;
1825
1826 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1827 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1828 return STATUS_NOT_IMPLEMENTED;
1829 }
1830
1831 static KSDISPATCH_TABLE PinDispatchTable =
1832 {
1833 IKsPin_DispatchDeviceIoControl,
1834 KsDispatchInvalidDeviceRequest,
1835 KsDispatchInvalidDeviceRequest,
1836 KsDispatchInvalidDeviceRequest,
1837 IKsPin_Close,
1838 KsDispatchQuerySecurity,
1839 KsDispatchSetSecurity,
1840 KsDispatchFastIoDeviceControlFailure,
1841 KsDispatchFastReadFailure,
1842 KsDispatchFastReadFailure
1843 };
1844
1845 NTSTATUS
1846 KspCreatePin(
1847 IN PDEVICE_OBJECT DeviceObject,
1848 IN PIRP Irp,
1849 IN PKSDEVICE KsDevice,
1850 IN IKsFilterFactory * FilterFactory,
1851 IN IKsFilter* Filter,
1852 IN PKSPIN_CONNECT Connect,
1853 IN KSPIN_DESCRIPTOR_EX* Descriptor)
1854 {
1855 IKsPinImpl * This;
1856 PIO_STACK_LOCATION IoStack;
1857 IKsDevice * Device;
1858 PDEVICE_EXTENSION DeviceExtension;
1859 PKSOBJECT_CREATE_ITEM CreateItem;
1860 NTSTATUS Status;
1861 PKSDATAFORMAT DataFormat;
1862 PKSBASIC_HEADER BasicHeader;
1863
1864 /* sanity checks */
1865 ASSERT(Descriptor->Dispatch);
1866
1867 DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
1868
1869 //Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
1870 //Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
1871
1872 /* get current irp stack */
1873 IoStack = IoGetCurrentIrpStackLocation(Irp);
1874
1875 /* get device extension */
1876 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1877
1878 /* get ks device interface */
1879 Device = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
1880
1881 /* first allocate pin ctx */
1882 This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
1883 if (!This)
1884 {
1885 /* not enough memory */
1886 return STATUS_INSUFFICIENT_RESOURCES;
1887 }
1888
1889 /* allocate create item */
1890 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
1891 if (!CreateItem)
1892 {
1893 /* not enough memory */
1894 FreeItem(This);
1895 DPRINT("KspCreatePin OutOfMemory\n");
1896 return STATUS_INSUFFICIENT_RESOURCES;
1897 }
1898
1899 /* initialize basic header */
1900 This->BasicHeader.KsDevice = KsDevice;
1901 This->BasicHeader.Type = KsObjectTypePin;
1902 This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
1903
1904 ASSERT(This->BasicHeader.Parent.KsFilter);
1905
1906 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
1907
1908 This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
1909 ASSERT(This->BasicHeader.ControlMutex);
1910
1911
1912 InitializeListHead(&This->BasicHeader.EventList);
1913 KeInitializeSpinLock(&This->BasicHeader.EventListLock);
1914
1915 /* initialize pin */
1916 This->lpVtbl = &vt_IKsPin;
1917 This->lpVtblReferenceClock = &vt_ReferenceClock;
1918 This->ref = 1;
1919 This->FileObject = IoStack->FileObject;
1920 This->Filter = Filter;
1921 KeInitializeMutex(&This->ProcessingMutex, 0);
1922 InitializeListHead(&This->IrpList);
1923 KeInitializeSpinLock(&This->IrpListLock);
1924
1925
1926 /* allocate object bag */
1927 This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1928 if (!This->Pin.Bag)
1929 {
1930 /* not enough memory */
1931 FreeItem(This);
1932 FreeItem(CreateItem);
1933 return STATUS_INSUFFICIENT_RESOURCES;
1934 }
1935
1936 /* initialize object bag */
1937 Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
1938
1939 /* get format */
1940 DataFormat = (PKSDATAFORMAT)(Connect + 1);
1941
1942 /* initialize pin descriptor */
1943 This->Pin.Descriptor = Descriptor;
1944 This->Pin.Context = NULL;
1945 This->Pin.Id = Connect->PinId;
1946 This->Pin.Communication = Descriptor->PinDescriptor.Communication;
1947 This->Pin.ConnectionIsExternal = FALSE; //FIXME
1948 RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
1949 RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
1950 RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
1951
1952 /* allocate format */
1953 Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
1954 if (!NT_SUCCESS(Status))
1955 {
1956 /* failed to allocate format */
1957 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1958 FreeItem(This);
1959 FreeItem(CreateItem);
1960 return STATUS_INSUFFICIENT_RESOURCES;
1961 }
1962
1963 /* copy format */
1964 RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
1965
1966 This->Pin.AttributeList = NULL; //FIXME
1967 This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
1968 This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
1969 This->Pin.DeviceState = KSSTATE_STOP;
1970 This->Pin.ResetState = KSRESET_END;
1971 This->Pin.ClientState = KSSTATE_STOP;
1972
1973 /* intialize allocator create item */
1974 CreateItem[0].Context = (PVOID)&This->Pin;
1975 CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
1976 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1977 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
1978
1979 /* intialize clock create item */
1980 CreateItem[1].Context = (PVOID)&This->Pin;
1981 CreateItem[1].Create = IKsPin_DispatchCreateClock;
1982 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1983 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
1984
1985 /* intialize topology node create item */
1986 CreateItem[2].Context = (PVOID)&This->Pin;
1987 CreateItem[2].Create = IKsPin_DispatchCreateNode;
1988 CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
1989 RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
1990
1991 /* now allocate object header */
1992 Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
1993 if (!NT_SUCCESS(Status))
1994 {
1995 /* failed to create object header */
1996 DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
1997 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
1998 FreeItem(This);
1999 FreeItem(CreateItem);
2000
2001 /* return failure code */
2002 return Status;
2003 }
2004
2005 /* add extra info to object header */
2006 This->ObjectHeader->Type = KsObjectTypePin;
2007 This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
2008 This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
2009
2010 if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
2011 {
2012 /* the pin is part of filter-centric processing filter
2013 * add process pin to filter
2014 */
2015 This->ProcessPin.BytesAvailable = 0;
2016 This->ProcessPin.BytesUsed = 0;
2017 This->ProcessPin.CopySource = NULL;
2018 This->ProcessPin.Data = NULL;
2019 This->ProcessPin.DelegateBranch = NULL;
2020 This->ProcessPin.Flags = 0;
2021 This->ProcessPin.InPlaceCounterpart = NULL;
2022 This->ProcessPin.Pin = &This->Pin;
2023 This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer;
2024 This->ProcessPin.Terminate = FALSE;
2025
2026 Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
2027 DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
2028
2029 if (!NT_SUCCESS(Status))
2030 {
2031 /* failed to add process pin */
2032 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2033 KsFreeObjectHeader(&This->ObjectHeader);
2034 FreeItem(This);
2035 FreeItem(CreateItem);
2036 /* return failure code */
2037 return Status;
2038 }
2039 }
2040
2041 /* FIXME add pin instance to filter instance */
2042
2043
2044 if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
2045 {
2046 Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
2047 DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
2048 DbgBreakPoint();
2049 }
2050
2051
2052 /* does the driver have a pin dispatch */
2053 if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
2054 {
2055 /* now inform the driver to create a new pin */
2056 Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
2057 DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
2058 }
2059
2060
2061
2062 DPRINT("KspCreatePin Status %lx\n", Status);
2063
2064 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
2065 {
2066 /* failed to create pin, release resources */
2067 KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
2068 KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
2069 FreeItem(This);
2070
2071 /* return failure code */
2072 return Status;
2073 }
2074
2075 return Status;
2076 }