ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pin.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/ksfilter/ks/worker.c
00005  * PURPOSE:         KS pin functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 typedef struct _KSISTREAM_POINTER
00013 {
00014     PFNKSSTREAMPOINTER Callback;
00015     PIRP Irp;
00016     KTIMER Timer;
00017     KDPC TimerDpc;
00018     struct _KSISTREAM_POINTER *Next;
00019     PKSPIN Pin;
00020     PVOID Data;
00021     ULONG Offset;
00022     ULONG Length;
00023     KSSTREAM_POINTER StreamPointer;
00024     KSPIN_LOCK Lock;
00025 }KSISTREAM_POINTER, *PKSISTREAM_POINTER;
00026 
00027 typedef struct
00028 {
00029     KSBASIC_HEADER BasicHeader;
00030     KSPIN Pin;
00031     PKSIOBJECT_HEADER ObjectHeader;
00032     KSPROCESSPIN ProcessPin;
00033     LIST_ENTRY Entry;
00034 
00035     LONG ref;
00036 
00037     IKsFilter * Filter;
00038     KMUTEX ProcessingMutex;
00039     PFILE_OBJECT FileObject;
00040 
00041     PKSGATE AttachedGate;
00042     BOOL OrGate;
00043 
00044     LIST_ENTRY IrpList;
00045     KSPIN_LOCK IrpListLock;
00046     volatile LONG IrpCount;
00047 
00048     PKSISTREAM_POINTER ClonedStreamPointer;
00049     KSISTREAM_POINTER LeadingEdgeStreamPointer;
00050     KSISTREAM_POINTER TrailingStreamPointer;
00051 
00052     PFNKSPINPOWER  Sleep;
00053     PFNKSPINPOWER  Wake;
00054     PFNKSPINHANDSHAKE  Handshake;
00055     PFNKSPINFRAMERETURN  FrameReturn;
00056     PFNKSPINIRPCOMPLETION  IrpCompletion;
00057 
00058     KSCLOCK_FUNCTIONTABLE ClockTable;
00059     PFILE_OBJECT ClockFileObject;
00060     IKsReferenceClockVtbl * lpVtblReferenceClock;
00061     PKSDEFAULTCLOCK DefaultClock;
00062 
00063     PKSWORKER PinWorker;
00064     WORK_QUEUE_ITEM PinWorkQueueItem;
00065     KEVENT FrameComplete;
00066     ULONG FrameSize;
00067     ULONG NumFrames;
00068     PDMA_ADAPTER Dma;
00069     ULONG MapRegisters;
00070 
00071 }IKsPinImpl;
00072 
00073 NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00074 NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00075 NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00076 NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00077 NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00078 NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
00079 
00080 
00081 
00082 DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler);
00083 DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId);
00084 
00085 //TODO
00086 // KSPROPSETID_Connection
00087 //    KSPROPERTY_CONNECTION_ACQUIREORDERING
00088 // KSPROPSETID_StreamInterface
00089 //     KSPROPERTY_STREAMINTERFACE_HEADERSIZE
00090 
00091 KSPROPERTY_SET PinPropertySet[] =
00092 {
00093     {
00094         &KSPROPSETID_Connection,
00095         sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM),
00096         (const KSPROPERTY_ITEM*)&PinConnectionSet,
00097         0,
00098         NULL
00099     },
00100     {
00101         &KSPROPSETID_Stream,
00102         sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM),
00103         (const KSPROPERTY_ITEM*)&PinStreamSet,
00104         0,
00105         NULL
00106     }
00107 };
00108 
00109 const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
00110 const GUID KSPROPSETID_Stream                  = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
00111 const GUID KSPROPSETID_Clock                   = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
00112 
00113 NTSTATUS
00114 NTAPI
00115 IKsPin_PinStreamAllocator(
00116     IN PIRP Irp,
00117     IN PKSIDENTIFIER Request,
00118     IN OUT PVOID Data)
00119 {
00120     UNIMPLEMENTED
00121     return STATUS_NOT_IMPLEMENTED;
00122 }
00123 
00124 NTSTATUS
00125 NTAPI
00126 IKsPin_PinMasterClock(
00127     IN PIRP Irp,
00128     IN PKSIDENTIFIER Request,
00129     IN OUT PVOID Data)
00130 {
00131     PIO_STACK_LOCATION IoStack;
00132     PKSIOBJECT_HEADER ObjectHeader;
00133     IKsPinImpl * This;
00134     NTSTATUS Status = STATUS_SUCCESS;
00135     PHANDLE Handle;
00136     PFILE_OBJECT FileObject;
00137     KPROCESSOR_MODE Mode;
00138     KSPROPERTY Property;
00139     ULONG BytesReturned;
00140 
00141     /* get current irp stack */
00142     IoStack = IoGetCurrentIrpStackLocation(Irp);
00143 
00144     DPRINT("IKsPin_PinMasterClock\n");
00145 
00146     /* sanity check */
00147     ASSERT(IoStack->FileObject);
00148     ASSERT(IoStack->FileObject->FsContext2);
00149 
00150     /* get the object header */
00151     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
00152 
00153     /* sanity check */
00154     ASSERT(ObjectHeader);
00155 
00156     /* locate ks pin implemention from KSPIN offset */
00157     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
00158 
00159     /* sanity check */
00160     ASSERT(This);
00161 
00162     Handle = (PHANDLE)Data;
00163 
00164     if (Request->Flags & KSPROPERTY_TYPE_GET)
00165     {
00166         if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
00167             This->Pin.Descriptor->Dispatch &&
00168             (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
00169         {
00170             *Handle = NULL;
00171             Status = STATUS_SUCCESS;
00172         }
00173         else
00174         {
00175             /* no clock available */
00176             Status = STATUS_UNSUCCESSFUL;
00177         }
00178     }
00179     else if (Request->Flags & KSPROPERTY_TYPE_SET)
00180     {
00181         if (This->Pin.ClientState != KSSTATE_STOP)
00182         {
00183             /* can only set in stopped state */
00184             Status = STATUS_INVALID_DEVICE_STATE;
00185         }
00186         else
00187         {
00188             if (*Handle)
00189             {
00190                 Mode = ExGetPreviousMode();
00191 
00192                 Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
00193 
00194                 DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
00195                 if (NT_SUCCESS(Status))
00196                 {
00197                     Property.Set = KSPROPSETID_Clock;
00198                     Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
00199                     Property.Flags = KSPROPERTY_TYPE_GET;
00200 
00201                     Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned);
00202 
00203                     DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status);
00204 
00205                     if (NT_SUCCESS(Status))
00206                     {
00207                         This->ClockFileObject = FileObject;
00208                     }
00209                     else
00210                     {
00211                         ObDereferenceObject(FileObject);
00212                     }
00213                 }
00214             }
00215             else
00216             {
00217                 /* zeroing clock handle */
00218                 RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE));
00219                 Status = STATUS_SUCCESS;
00220                 if (This->ClockFileObject)
00221                 {
00222                     FileObject = This->ClockFileObject;
00223                     This->ClockFileObject = NULL;
00224 
00225                     ObDereferenceObject(This->ClockFileObject);
00226                 }
00227             }
00228         }
00229     }
00230 
00231     DPRINT("IKsPin_PinMasterClock Status %lx\n", Status);
00232     return Status;
00233 }
00234 
00235 
00236 
00237 NTSTATUS
00238 NTAPI
00239 IKsPin_PinPipeId(
00240     IN PIRP Irp,
00241     IN PKSIDENTIFIER Request,
00242     IN OUT PVOID Data)
00243 {
00244     UNIMPLEMENTED
00245     return STATUS_NOT_IMPLEMENTED;
00246 }
00247 
00248 
00249 NTSTATUS
00250 NTAPI
00251 IKsPin_PinStatePropertyHandler(
00252     IN PIRP Irp,
00253     IN PKSIDENTIFIER Request,
00254     IN OUT PVOID Data)
00255 {
00256     PIO_STACK_LOCATION IoStack;
00257     PKSIOBJECT_HEADER ObjectHeader;
00258     IKsPinImpl * This;
00259     NTSTATUS Status = STATUS_SUCCESS;
00260     KSSTATE OldState;
00261     PKSSTATE NewState;
00262 
00263     /* get current irp stack */
00264     IoStack = IoGetCurrentIrpStackLocation(Irp);
00265 
00266     DPRINT("IKsPin_PinStatePropertyHandler\n");
00267 
00268     /* sanity check */
00269     ASSERT(IoStack->FileObject);
00270     ASSERT(IoStack->FileObject->FsContext2);
00271 
00272     /* get the object header */
00273     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
00274 
00275     /* locate ks pin implemention from KSPIN offset */
00276     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
00277 
00278     /* acquire control mutex */
00279     KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
00280 
00281     /* grab state */
00282     NewState = (PKSSTATE)Data;
00283 
00284     if (Request->Flags & KSPROPERTY_TYPE_GET)
00285     {
00286         *NewState = This->Pin.DeviceState;
00287         Irp->IoStatus.Information = sizeof(KSSTATE);
00288     }
00289     else if (Request->Flags & KSPROPERTY_TYPE_SET)
00290     {
00291         if (This->Pin.Descriptor->Dispatch->SetDeviceState)
00292         {
00293             /* backup old state */
00294             OldState = This->Pin.ClientState;
00295 
00296             /* set new state */
00297             This->Pin.ClientState  = *NewState;
00298             This->Pin.DeviceState = KSSTATE_RUN;
00299 
00300             /* check if it supported */
00301             Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState);
00302 
00303             DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status);
00304 
00305             if (!NT_SUCCESS(Status))
00306             {
00307                 /* revert to old state */
00308                 This->Pin.ClientState = OldState;
00309                 This->Pin.DeviceState = OldState;
00310                 DPRINT("IKsPin_PinStatePropertyHandler failed to set state %lx Result %lx\n", *NewState, Status);
00311                 DbgBreakPoint();
00312             }
00313             else
00314             {
00315                 /* update device state */
00316                 This->Pin.DeviceState = *NewState;
00317             }
00318         }
00319         else
00320         {
00321             /* just set new state */
00322             This->Pin.DeviceState = *NewState;
00323             This->Pin.ClientState = *NewState;
00324         }
00325     }
00326 
00327     /* release processing mutex */
00328     KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
00329 
00330     DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
00331     return Status;
00332 }
00333 
00334 NTSTATUS
00335 NTAPI
00336 IKsPin_PinAllocatorFramingPropertyHandler(
00337     IN PIRP Irp,
00338     IN PKSIDENTIFIER Request,
00339     IN OUT PVOID Data)
00340 {
00341     PIO_STACK_LOCATION IoStack;
00342     PKSIOBJECT_HEADER ObjectHeader;
00343     IKsPinImpl * This;
00344     ULONG Size;
00345     NTSTATUS Status = STATUS_SUCCESS;
00346 
00347     /* get current irp stack */
00348     IoStack = IoGetCurrentIrpStackLocation(Irp);
00349 
00350     /* sanity check */
00351     ASSERT(IoStack->FileObject);
00352     ASSERT(IoStack->FileObject->FsContext2);
00353 
00354     /* get the object header */
00355     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
00356 
00357     /* locate ks pin implemention from KSPIN offset */
00358     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
00359 
00360     /* setting allocator flags is not supported */
00361     ASSERT(!(Request->Flags & KSPROPERTY_TYPE_SET));
00362 
00363     /* acquire control mutex */
00364     KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
00365 
00366     if (This->Pin.Descriptor->AllocatorFraming)
00367     {
00368         /* calculate size */
00369         Size = FIELD_OFFSET(KSALLOCATOR_FRAMING_EX, FramingItem[0]) + This->Pin.Descriptor->AllocatorFraming->CountItems * sizeof(KS_FRAMING_ITEM);
00370 
00371         if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
00372         {
00373             /* no buffer */
00374             Status = STATUS_BUFFER_OVERFLOW;
00375         }
00376         else if (Size > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
00377         {
00378             /* buffer too small */
00379             Status = STATUS_BUFFER_TOO_SMALL;
00380         }
00381         else
00382         {
00383             /* copy buffer */
00384             RtlMoveMemory(Data, This->Pin.Descriptor->AllocatorFraming, Size);
00385         }
00386 
00387         /* store size */
00388         Irp->IoStatus.Information = Size;
00389     }
00390     else
00391     {
00392         /* no allocator framing details */
00393         Status = STATUS_NOT_FOUND;
00394     }
00395 
00396     /* release processing mutex */
00397     KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
00398 
00399     DPRINT("IKsPin_PinAllocatorFramingPropertyHandler Status %lx\n", Status);
00400 
00401     return Status;
00402 }
00403 
00404 NTSTATUS
00405 NTAPI
00406 IKsPin_PinDataFormatPropertyHandler(
00407     IN PIRP Irp,
00408     IN PKSPROPERTY Request,
00409     IN OUT PVOID Data)
00410 {
00411     PIO_STACK_LOCATION IoStack;
00412     PKSIOBJECT_HEADER ObjectHeader;
00413     IKsPinImpl * This;
00414     NTSTATUS Status = STATUS_SUCCESS;
00415 
00416     /* get current irp stack */
00417     IoStack = IoGetCurrentIrpStackLocation(Irp);
00418 
00419     DPRINT("IKsPin_PinDataFormatPropertyHandler\n");
00420 
00421     /* sanity check */
00422     ASSERT(IoStack->FileObject);
00423     ASSERT(IoStack->FileObject->FsContext2);
00424 
00425     /* get the object header */
00426     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
00427 
00428     /* locate ks pin implemention from KSPIN offset */
00429     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
00430 
00431     /* acquire control mutex */
00432     KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
00433 
00434     if (Request->Flags & KSPROPERTY_TYPE_GET)
00435     {
00436         if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize)
00437         {
00438             /* buffer too small */
00439             Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize;
00440             Status = STATUS_BUFFER_TOO_SMALL;
00441         }
00442         else
00443         {
00444             /* copy format */
00445             RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize);
00446         }
00447     }
00448     else if (Request->Flags & KSPROPERTY_TYPE_SET)
00449     {
00450         /* set format */
00451         if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT)
00452         {
00453             /* format cannot be changed */
00454             Status = STATUS_INVALID_DEVICE_REQUEST;
00455         }
00456         else
00457         {
00458             /* FIXME check if the format is supported */
00459             Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0);
00460 
00461             if (NT_SUCCESS(Status))
00462             {
00463                 /* store new format */
00464                 RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
00465             }
00466         }
00467     }
00468 
00469     /* release processing mutex */
00470     KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
00471 
00472     DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status);
00473 
00474     return Status;
00475 }
00476 
00477 NTSTATUS
00478 NTAPI
00479 IKsPin_fnQueryInterface(
00480     IKsPin * iface,
00481     IN  REFIID refiid,
00482     OUT PVOID* Output)
00483 {
00484     NTSTATUS Status;
00485     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
00486 
00487     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
00488     {
00489         *Output = &This->BasicHeader.OuterUnknown;
00490         _InterlockedIncrement(&This->ref);
00491         return STATUS_SUCCESS;
00492     }
00493 
00494 
00495     if (This->BasicHeader.ClientAggregate)
00496     {
00497          /* using client aggregate */
00498          Status = This->BasicHeader.ClientAggregate->lpVtbl->QueryInterface(This->BasicHeader.ClientAggregate, refiid, Output);
00499 
00500          if (NT_SUCCESS(Status))
00501          {
00502              /* client aggregate supports interface */
00503              return Status;
00504          }
00505     }
00506 
00507     DPRINT("IKsPin_fnQueryInterface no interface\n");
00508     return STATUS_NOT_SUPPORTED;
00509 }
00510 
00511 ULONG
00512 NTAPI
00513 IKsPin_fnAddRef(
00514     IKsPin * iface)
00515 {
00516     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
00517 
00518     return InterlockedIncrement(&This->ref);
00519 }
00520 
00521 ULONG
00522 NTAPI
00523 IKsPin_fnRelease(
00524     IKsPin * iface)
00525 {
00526     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, BasicHeader.OuterUnknown);
00527 
00528     InterlockedDecrement(&This->ref);
00529 
00530     if (This->ref == 0)
00531     {
00532         FreeItem(This);
00533         return 0;
00534     }
00535     /* Return new reference count */
00536     return This->ref;
00537 }
00538 
00539 NTSTATUS
00540 NTAPI
00541 IKsPin_fnTransferKsIrp(
00542     IN IKsPin *iface,
00543     IN PIRP Irp,
00544     IN IKsTransport **OutTransport)
00545 {
00546     UNIMPLEMENTED
00547     return STATUS_NOT_IMPLEMENTED;
00548 }
00549 
00550 VOID
00551 NTAPI
00552 IKsPin_fnDiscardKsIrp(
00553     IN IKsPin *iface,
00554     IN PIRP Irp,
00555     IN IKsTransport * *OutTransport)
00556 {
00557     UNIMPLEMENTED
00558 }
00559 
00560 
00561 NTSTATUS
00562 NTAPI
00563 IKsPin_fnConnect(
00564     IN IKsPin *iface,
00565     IN IKsTransport * TransportIn,
00566     OUT IKsTransport ** OutTransportIn,
00567     OUT IKsTransport * *OutTransportOut,
00568     IN KSPIN_DATAFLOW DataFlow)
00569 {
00570     UNIMPLEMENTED
00571     return STATUS_NOT_IMPLEMENTED;
00572 }
00573 
00574 NTSTATUS
00575 NTAPI
00576 IKsPin_fnSetDeviceState(
00577     IN IKsPin *iface,
00578     IN KSSTATE OldState,
00579     IN KSSTATE NewState,
00580     IN IKsTransport * *OutTransport)
00581 {
00582     UNIMPLEMENTED
00583     return STATUS_NOT_IMPLEMENTED;
00584 }
00585 
00586 VOID
00587 NTAPI
00588 IKsPin_fnSetResetState(
00589     IN IKsPin *iface,
00590     IN KSRESET ResetState,
00591     OUT IKsTransport * * OutTransportOut)
00592 {
00593     UNIMPLEMENTED
00594 }
00595 
00596 NTSTATUS
00597 NTAPI
00598 IKsPin_fnGetTransportConfig(
00599     IN IKsPin *iface,
00600     IN struct KSPTRANSPORTCONFIG * TransportConfig,
00601     OUT IKsTransport ** OutTransportIn,
00602     OUT IKsTransport ** OutTransportOut)
00603 {
00604     UNIMPLEMENTED
00605     return STATUS_NOT_IMPLEMENTED;
00606 }
00607 
00608 NTSTATUS
00609 NTAPI
00610 IKsPin_fnSetTransportConfig(
00611     IN IKsPin *iface,
00612     IN struct KSPTRANSPORTCONFIG const * TransportConfig,
00613     OUT IKsTransport ** OutTransportIn,
00614     OUT IKsTransport ** OutTransportOut)
00615 {
00616     UNIMPLEMENTED
00617     return STATUS_NOT_IMPLEMENTED;
00618 }
00619 
00620 NTSTATUS
00621 NTAPI
00622 IKsPin_fnResetTransportConfig(
00623     IN IKsPin *iface,
00624     OUT IKsTransport ** OutTransportIn,
00625     OUT IKsTransport ** OutTransportOut)
00626 {
00627     UNIMPLEMENTED
00628     return STATUS_NOT_IMPLEMENTED;
00629 }
00630 
00631 PKSPIN
00632 NTAPI
00633 IKsPin_fnGetStruct(
00634     IN IKsPin *iface)
00635 {
00636     UNIMPLEMENTED
00637     return NULL;
00638 }
00639 
00640 PKSPROCESSPIN
00641 NTAPI
00642 IKsPin_fnGetProcessPin(
00643     IN IKsPin *iface)
00644 {
00645     UNIMPLEMENTED
00646     return NULL;
00647 }
00648 
00649 NTSTATUS
00650 NTAPI
00651 IKsPin_fnAttemptBypass(
00652     IN IKsPin *iface)
00653 {
00654     UNIMPLEMENTED
00655     return STATUS_NOT_IMPLEMENTED;
00656 }
00657 
00658 NTSTATUS
00659 NTAPI
00660 IKsPin_fnAttemptUnbypass(
00661     IN IKsPin *iface)
00662 {
00663     UNIMPLEMENTED
00664     return STATUS_NOT_IMPLEMENTED;
00665 }
00666 
00667 VOID
00668 NTAPI
00669 IKsPin_fnGenerateConnectionEvents(
00670     IN IKsPin *iface,
00671     IN ULONG EventMask)
00672 {
00673     UNIMPLEMENTED
00674 }
00675 
00676 NTSTATUS
00677 NTAPI
00678 IKsPin_fnClientSetDeviceState(
00679     IN IKsPin *iface,
00680     IN KSSTATE StateIn,
00681     IN KSSTATE StateOut)
00682 {
00683     UNIMPLEMENTED
00684     return STATUS_NOT_IMPLEMENTED;
00685 }
00686 
00687 static IKsPinVtbl vt_IKsPin =
00688 {
00689     IKsPin_fnQueryInterface,
00690     IKsPin_fnAddRef,
00691     IKsPin_fnRelease,
00692     IKsPin_fnTransferKsIrp,
00693     IKsPin_fnDiscardKsIrp,
00694     IKsPin_fnConnect,
00695     IKsPin_fnSetDeviceState,
00696     IKsPin_fnSetResetState,
00697     IKsPin_fnGetTransportConfig,
00698     IKsPin_fnSetTransportConfig,
00699     IKsPin_fnResetTransportConfig,
00700     IKsPin_fnGetStruct,
00701     IKsPin_fnGetProcessPin,
00702     IKsPin_fnAttemptBypass,
00703     IKsPin_fnAttemptUnbypass,
00704     IKsPin_fnGenerateConnectionEvents,
00705     IKsPin_fnClientSetDeviceState
00706 };
00707 
00708 
00709 //==============================================================
00710 
00711 NTSTATUS
00712 NTAPI
00713 IKsReferenceClock_fnQueryInterface(
00714     IKsReferenceClock * iface,
00715     IN  REFIID refiid,
00716     OUT PVOID* Output)
00717 {
00718     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00719 
00720     return IKsPin_fnQueryInterface((IKsPin*)&This->BasicHeader.OuterUnknown, refiid, Output);
00721 }
00722 
00723 ULONG
00724 NTAPI
00725 IKsReferenceClock_fnAddRef(
00726     IKsReferenceClock * iface)
00727 {
00728     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00729 
00730     return IKsPin_fnAddRef((IKsPin*)&This->BasicHeader.OuterUnknown);
00731 }
00732 
00733 ULONG
00734 NTAPI
00735 IKsReferenceClock_fnRelease(
00736     IKsReferenceClock * iface)
00737 {
00738     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00739 
00740     return IKsPin_fnRelease((IKsPin*)&This->BasicHeader.OuterUnknown);
00741 }
00742 
00743 LONGLONG
00744 NTAPI
00745 IKsReferenceClock_fnGetTime(
00746     IKsReferenceClock * iface)
00747 {
00748     LONGLONG Result;
00749 
00750     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00751 
00752 
00753     DPRINT1("IKsReferenceClock_fnGetTime\n");
00754 
00755     if (!This->ClockFileObject || !This->ClockTable.GetTime)
00756     {
00757         Result = 0;
00758     }
00759     else
00760     {
00761         Result = This->ClockTable.GetTime(This->ClockFileObject);
00762     }
00763 
00764     return Result;
00765 }
00766 
00767 LONGLONG
00768 NTAPI
00769 IKsReferenceClock_fnGetPhysicalTime(
00770     IKsReferenceClock * iface)
00771 {
00772     LONGLONG Result;
00773 
00774     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00775 
00776     DPRINT1("IKsReferenceClock_fnGetPhysicalTime\n");
00777 
00778 
00779     if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime)
00780     {
00781         Result = 0;
00782     }
00783     else
00784     {
00785         Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject);
00786     }
00787 
00788     return Result;
00789 }
00790 
00791 
00792 LONGLONG
00793 NTAPI
00794 IKsReferenceClock_fnGetCorrelatedTime(
00795     IKsReferenceClock * iface,
00796     OUT PLONGLONG SystemTime)
00797 {
00798     LONGLONG Result;
00799 
00800     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00801 
00802     DPRINT1("IKsReferenceClock_fnGetCorrelatedTime\n");
00803 
00804     if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime)
00805     {
00806         Result = 0;
00807     }
00808     else
00809     {
00810         Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime);
00811     }
00812 
00813     return Result;
00814 }
00815 
00816 
00817 LONGLONG
00818 NTAPI
00819 IKsReferenceClock_fnGetCorrelatedPhysicalTime(
00820     IKsReferenceClock * iface,
00821     OUT PLONGLONG SystemTime)
00822 {
00823     LONGLONG Result;
00824 
00825     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00826 
00827     DPRINT1("IKsReferenceClock_fnGetCorrelatedPhysicalTime\n");
00828 
00829     if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime)
00830     {
00831         Result = 0;
00832     }
00833     else
00834     {
00835         Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime);
00836     }
00837 
00838     return Result;
00839 }
00840 
00841 NTSTATUS
00842 NTAPI
00843 IKsReferenceClock_fnGetResolution(
00844     IKsReferenceClock * iface,
00845     OUT PKSRESOLUTION Resolution)
00846 {
00847     KSPROPERTY Property;
00848     ULONG BytesReturned;
00849 
00850     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00851 
00852     DPRINT1("IKsReferenceClock_fnGetResolution\n");
00853 
00854     if (!This->ClockFileObject)
00855     {
00856         Resolution->Error = 0;
00857         Resolution->Granularity = 1;
00858         DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n");
00859         return STATUS_SUCCESS;
00860     }
00861 
00862 
00863     if (!This->ClockFileObject)
00864         return STATUS_DEVICE_NOT_READY;
00865 
00866 
00867     Property.Set = KSPROPSETID_Clock;
00868     Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
00869     Property.Flags = KSPROPERTY_TYPE_GET;
00870 
00871     return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned);
00872 
00873 }
00874 
00875 NTSTATUS
00876 NTAPI
00877 IKsReferenceClock_fnGetState(
00878     IKsReferenceClock * iface,
00879      OUT PKSSTATE State)
00880 {
00881     KSPROPERTY Property;
00882     ULONG BytesReturned;
00883 
00884     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
00885 
00886     DPRINT1("IKsReferenceClock_fnGetState\n");
00887 
00888     if (!This->ClockFileObject)
00889     {
00890         *State = This->Pin.ClientState;
00891         DPRINT1("IKsReferenceClock_fnGetState Using HACK\n");
00892         return STATUS_SUCCESS;
00893     }
00894 
00895 
00896     if (!This->ClockFileObject)
00897         return STATUS_DEVICE_NOT_READY;
00898 
00899 
00900     Property.Set = KSPROPSETID_Clock;
00901     Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
00902     Property.Flags = KSPROPERTY_TYPE_GET;
00903 
00904     return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned);
00905 }
00906 
00907 static IKsReferenceClockVtbl vt_ReferenceClock =
00908 {
00909     IKsReferenceClock_fnQueryInterface,
00910     IKsReferenceClock_fnAddRef,
00911     IKsReferenceClock_fnRelease,
00912     IKsReferenceClock_fnGetTime,
00913     IKsReferenceClock_fnGetPhysicalTime,
00914     IKsReferenceClock_fnGetCorrelatedTime,
00915     IKsReferenceClock_fnGetCorrelatedPhysicalTime,
00916     IKsReferenceClock_fnGetResolution,
00917     IKsReferenceClock_fnGetState
00918 };
00919 
00920 
00921 //==============================================================
00922 
00923 
00924 /*
00925     @implemented
00926 */
00927 VOID
00928 NTAPI
00929 KsPinAcquireProcessingMutex(
00930     IN PKSPIN  Pin)
00931 {
00932     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
00933 
00934     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
00935 }
00936 
00937 /*
00938     @implemented
00939 */
00940 VOID
00941 NTAPI
00942 KsPinAttachAndGate(
00943     IN PKSPIN Pin,
00944     IN PKSGATE AndGate OPTIONAL)
00945 {
00946     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
00947 
00948     /* FIXME attach to filter's and gate (filter-centric processing) */
00949 
00950     This->AttachedGate = AndGate;
00951     This->OrGate = FALSE;
00952 }
00953 
00954 /*
00955     @implemented
00956 */
00957 VOID
00958 NTAPI
00959 KsPinAttachOrGate(
00960     IN PKSPIN Pin,
00961     IN PKSGATE OrGate OPTIONAL)
00962 {
00963     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
00964 
00965     /* FIXME attach to filter's and gate (filter-centric processing) */
00966 
00967     This->AttachedGate = OrGate;
00968     This->OrGate = TRUE;
00969 }
00970 
00971 /*
00972     @implemented
00973 */
00974 PKSGATE
00975 NTAPI
00976 KsPinGetAndGate(
00977     IN PKSPIN  Pin)
00978 {
00979     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
00980 
00981     return This->AttachedGate;
00982 }
00983 
00984 /*
00985     @unimplemented
00986 */
00987 VOID
00988 NTAPI
00989 KsPinAttemptProcessing(
00990     IN PKSPIN  Pin,
00991     IN BOOLEAN  Asynchronous)
00992 {
00993     DPRINT("KsPinAttemptProcessing\n");
00994     DbgBreakPoint();
00995     UNIMPLEMENTED
00996 }
00997 
00998 /*
00999     @unimplemented
01000 */
01001 NTSTATUS
01002 NTAPI
01003 KsPinGetAvailableByteCount(
01004     IN PKSPIN  Pin,
01005     OUT PLONG  InputDataBytes OPTIONAL,
01006     OUT PLONG  OutputBufferBytes OPTIONAL)
01007 {
01008     UNIMPLEMENTED
01009     return STATUS_NOT_IMPLEMENTED;
01010 }
01011 
01012 /*
01013     @unimplemented
01014 */
01015 NTSTATUS
01016 NTAPI
01017 KsPinGetConnectedFilterInterface(
01018     IN PKSPIN  Pin,
01019     IN const GUID*  InterfaceId,
01020     OUT PVOID*  Interface)
01021 {
01022     UNIMPLEMENTED
01023     return STATUS_NOT_IMPLEMENTED;
01024 }
01025 
01026 /*
01027     @unimplemented
01028 */
01029 PDEVICE_OBJECT
01030 NTAPI
01031 KsPinGetConnectedPinDeviceObject(
01032     IN PKSPIN Pin)
01033 {
01034     UNIMPLEMENTED
01035     return NULL;
01036 }
01037 
01038 /*
01039     @unimplemented
01040 */
01041 PFILE_OBJECT
01042 NTAPI
01043 KsPinGetConnectedPinFileObject(
01044     IN PKSPIN Pin)
01045 {
01046     UNIMPLEMENTED
01047     return NULL;
01048 }
01049 
01050 /*
01051     @unimplemented
01052 */
01053 NTSTATUS
01054 NTAPI
01055 KsPinGetConnectedPinInterface(
01056     IN PKSPIN  Pin,
01057     IN const GUID*  InterfaceId,
01058     OUT PVOID*  Interface)
01059 {
01060     UNIMPLEMENTED
01061     return STATUS_NOT_IMPLEMENTED;
01062 }
01063 
01064 /*
01065     @unimplemented
01066 */
01067 VOID
01068 NTAPI
01069 KsPinGetCopyRelationships(
01070     IN PKSPIN Pin,
01071     OUT PKSPIN* CopySource,
01072     OUT PKSPIN* DelegateBranch)
01073 {
01074     UNIMPLEMENTED
01075 }
01076 
01077 /*
01078     @implemented
01079 */
01080 PKSPIN
01081 NTAPI
01082 KsPinGetNextSiblingPin(
01083     IN PKSPIN  Pin)
01084 {
01085     return KsGetNextSibling((PVOID)Pin);
01086 }
01087 
01088 /*
01089     @implemented
01090 */
01091 PKSFILTER
01092 NTAPI
01093 KsPinGetParentFilter(
01094     IN PKSPIN  Pin)
01095 {
01096     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01097 
01098     /* return parent filter */
01099     return This->BasicHeader.Parent.KsFilter;
01100 }
01101 
01102 /*
01103     @implemented
01104 */
01105 NTSTATUS
01106 NTAPI
01107 KsPinGetReferenceClockInterface(
01108     IN PKSPIN  Pin,
01109     OUT PIKSREFERENCECLOCK*  Interface)
01110 {
01111     NTSTATUS Status = STATUS_DEVICE_NOT_READY;
01112     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01113 
01114     if (This->ClockFileObject)
01115     {
01116         /* clock is available */
01117         *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
01118         Status = STATUS_SUCCESS;
01119     }
01120 
01121     DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status);
01122     return Status;
01123 }
01124 
01125 /*
01126     @implemented
01127 */
01128 VOID
01129 NTAPI
01130 KsPinRegisterFrameReturnCallback(
01131     IN PKSPIN  Pin,
01132     IN PFNKSPINFRAMERETURN  FrameReturn)
01133 {
01134     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01135 
01136     /* register frame return callback */
01137     This->FrameReturn = FrameReturn;
01138 }
01139 
01140 /*
01141     @implemented
01142 */
01143 VOID
01144 NTAPI
01145 KsPinRegisterHandshakeCallback(
01146     IN PKSPIN  Pin,
01147     IN PFNKSPINHANDSHAKE  Handshake)
01148 {
01149     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01150 
01151     /* register private protocol handshake callback */
01152     This->Handshake = Handshake;
01153 }
01154 
01155 /*
01156     @implemented
01157 */
01158 VOID
01159 NTAPI
01160 KsPinRegisterIrpCompletionCallback(
01161     IN PKSPIN  Pin,
01162     IN PFNKSPINIRPCOMPLETION  IrpCompletion)
01163 {
01164     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01165 
01166     /* register irp completion callback */
01167     This->IrpCompletion = IrpCompletion;
01168 }
01169 
01170 /*
01171     @implemented
01172 */
01173 VOID
01174 NTAPI
01175 KsPinRegisterPowerCallbacks(
01176     IN PKSPIN  Pin,
01177     IN PFNKSPINPOWER  Sleep OPTIONAL,
01178     IN PFNKSPINPOWER  Wake OPTIONAL)
01179 {
01180     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01181 
01182     /* register power callbacks */
01183     This->Sleep = Sleep;
01184     This->Wake = Wake;
01185 }
01186 
01187 /*
01188     @implemented
01189 */
01190 VOID
01191 NTAPI
01192 KsPinReleaseProcessingMutex(
01193     IN PKSPIN  Pin)
01194 {
01195     IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01196 
01197     /* release processing mutex */
01198     KeReleaseMutex(&This->ProcessingMutex, FALSE);
01199 }
01200 
01201 /*
01202     @implemented
01203 */
01204 KSDDKAPI
01205 PKSPIN
01206 NTAPI
01207 KsGetPinFromIrp(
01208     IN PIRP Irp)
01209 {
01210     PKSIOBJECT_HEADER ObjectHeader;
01211     PKSPIN Pin;
01212     PKSBASIC_HEADER Header;
01213     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
01214 
01215     DPRINT("KsGetPinFromIrp\n");
01216 
01217     /* get object header */
01218     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
01219 
01220     if (!ObjectHeader)
01221         return NULL;
01222 
01223     Pin = (PKSPIN)ObjectHeader->ObjectType;
01224     Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER));
01225 
01226     /* sanity check */
01227     ASSERT(Header->Type == KsObjectTypePin);
01228 
01229     /* return object type */
01230     return Pin;
01231 }
01232 
01233 
01234 
01235 /*
01236     @unimplemented
01237 */
01238 VOID
01239 NTAPI
01240 KsPinSetPinClockTime(
01241     IN PKSPIN  Pin,
01242     IN LONGLONG  Time)
01243 {
01244     UNIMPLEMENTED
01245 }
01246 
01247 /*
01248     @unimplemented
01249 */
01250 NTSTATUS
01251 NTAPI
01252 KsPinSubmitFrame(
01253     IN PKSPIN  Pin,
01254     IN PVOID  Data  OPTIONAL,
01255     IN ULONG  Size  OPTIONAL,
01256     IN PKSSTREAM_HEADER  StreamHeader  OPTIONAL,
01257     IN PVOID  Context  OPTIONAL)
01258 {
01259     UNIMPLEMENTED
01260     return STATUS_UNSUCCESSFUL;
01261 }
01262 
01263 /*
01264     @unimplemented
01265 */
01266 KSDDKAPI
01267 NTSTATUS
01268 NTAPI
01269 KsPinSubmitFrameMdl(
01270     IN PKSPIN  Pin,
01271     IN PMDL  Mdl  OPTIONAL,
01272     IN PKSSTREAM_HEADER  StreamHeader  OPTIONAL,
01273     IN PVOID  Context  OPTIONAL)
01274 {
01275     UNIMPLEMENTED
01276     return STATUS_UNSUCCESSFUL;
01277 }
01278 
01279 /*
01280     @unimplemented
01281 */
01282 KSDDKAPI
01283 BOOLEAN
01284 NTAPI
01285 KsProcessPinUpdate(
01286     IN PKSPROCESSPIN  ProcessPin)
01287 {
01288     UNIMPLEMENTED
01289     return FALSE;
01290 }
01291 
01292 NTSTATUS
01293 IKsPin_PrepareStreamHeader(
01294     IN IKsPinImpl * This,
01295     IN PKSISTREAM_POINTER StreamPointer)
01296 {
01297     PKSSTREAM_HEADER Header;
01298     ULONG Length;
01299 
01300     /* grab new irp */
01301     StreamPointer->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
01302     if (!StreamPointer->Irp)
01303     {
01304         /* run out of mappings */
01305         DPRINT("OutOfMappings\n");
01306         return STATUS_DEVICE_NOT_READY;
01307     }
01308 
01309     InterlockedDecrement(&This->IrpCount);
01310     KsDecrementCountedWorker(This->PinWorker);
01311 
01312     /* get stream header */
01313     if (StreamPointer->Irp->RequestorMode == UserMode)
01314         Header = (PKSSTREAM_HEADER)StreamPointer->Irp->AssociatedIrp.SystemBuffer;
01315     else
01316         Header = (PKSSTREAM_HEADER)StreamPointer->Irp->UserBuffer;
01317 
01318     /* initialize stream pointer */
01319     StreamPointer->Callback = NULL;
01320     StreamPointer->Length = max(Header->DataUsed, Header->FrameExtent);
01321     StreamPointer->Next = NULL;
01322     StreamPointer->Offset = 0;
01323     StreamPointer->Pin = &This->Pin;
01324     StreamPointer->Data = Header->Data;
01325 
01326     StreamPointer->StreamPointer.Context = NULL;
01327     StreamPointer->StreamPointer.Pin = &This->Pin;
01328     StreamPointer->StreamPointer.StreamHeader = Header;
01329 
01330     if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
01331         StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetIn;
01332     else
01333     StreamPointer->StreamPointer.Offset = &StreamPointer->StreamPointer.OffsetOut;
01334 
01335 #ifndef _WIN64
01336     StreamPointer->StreamPointer.Offset->Alignment = 0;
01337 #endif
01338     StreamPointer->StreamPointer.Offset->Count = 0;
01339     StreamPointer->StreamPointer.Offset->Data = NULL;
01340     StreamPointer->StreamPointer.Offset->Remaining = 0;
01341 
01342     ASSERT(StreamPointer->StreamPointer.Offset->Remaining == 0);
01343 
01344     //StreamPointer->Offset += StreamPointer->StreamPointer.Offset->Count;
01345 
01346     ASSERT(StreamPointer->Length > StreamPointer->Offset);
01347     ASSERT(StreamPointer->StreamPointer.StreamHeader);
01348     ASSERT(This->FrameSize);
01349 
01350     /* calculate length */
01351     /* TODO split into frames */
01352     Length = StreamPointer->Length;
01353 
01354     /* FIXME */
01355     ASSERT(Length);
01356 
01357 #ifndef _WIN64
01358     StreamPointer->StreamPointer.Offset->Alignment = 0;
01359 #endif
01360     StreamPointer->StreamPointer.Context = NULL;
01361     StreamPointer->StreamPointer.Pin = &This->Pin;
01362     StreamPointer->StreamPointer.Offset->Count = Length;
01363     StreamPointer->StreamPointer.Offset->Remaining = Length;
01364     StreamPointer->StreamPointer.Offset->Data = (PVOID)((ULONG_PTR)StreamPointer->Data + StreamPointer->Offset);
01365     StreamPointer->StreamPointer.StreamHeader->FrameExtent = Length;
01366     if (StreamPointer->StreamPointer.StreamHeader->DataUsed)
01367         StreamPointer->StreamPointer.StreamHeader->DataUsed = Length;
01368 
01369     StreamPointer->StreamPointer.StreamHeader->Data = StreamPointer->StreamPointer.Offset->Data;
01370 
01371     return STATUS_SUCCESS;
01372 }
01373 
01374 
01375 /*
01376     @unimplemented
01377 */
01378 KSDDKAPI
01379 PKSSTREAM_POINTER
01380 NTAPI
01381 KsPinGetLeadingEdgeStreamPointer(
01382     IN PKSPIN Pin,
01383     IN KSSTREAM_POINTER_STATE State)
01384 {
01385     IKsPinImpl * This;
01386     NTSTATUS Status;
01387 
01388     This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01389 
01390     DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State,
01391            This->LeadingEdgeStreamPointer.Length,
01392            This->LeadingEdgeStreamPointer.Offset);
01393 
01394     /* sanity check */
01395     ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED);
01396 
01397     if (State == KSSTREAM_POINTER_STATE_LOCKED)
01398     {
01399         if (!This->LeadingEdgeStreamPointer.Irp || This->LeadingEdgeStreamPointer.StreamPointer.Offset->Remaining == 0)
01400         {
01401             Status = IKsPin_PrepareStreamHeader(This, &This->LeadingEdgeStreamPointer);
01402             if (!NT_SUCCESS(Status))
01403                 return NULL;
01404         }
01405 
01406         DPRINT("KsPinGetLeadingEdgeStreamPointer NewOffset %lu TotalLength %lu\n", This->LeadingEdgeStreamPointer.Offset, This->LeadingEdgeStreamPointer.Length);
01407     }
01408 
01409      return &This->LeadingEdgeStreamPointer.StreamPointer;
01410 }
01411 
01412 /*
01413     @unimplemented
01414 */
01415 KSDDKAPI
01416 PKSSTREAM_POINTER
01417 NTAPI
01418 KsPinGetTrailingEdgeStreamPointer(
01419     IN PKSPIN Pin,
01420     IN KSSTREAM_POINTER_STATE State)
01421 {
01422     UNIMPLEMENTED
01423     return NULL;
01424 }
01425 
01426 /*
01427     @unimplemented
01428 */
01429 KSDDKAPI
01430 NTSTATUS
01431 NTAPI
01432 KsStreamPointerSetStatusCode(
01433     IN PKSSTREAM_POINTER StreamPointer,
01434     IN NTSTATUS Status)
01435 {
01436     UNIMPLEMENTED
01437     return STATUS_UNSUCCESSFUL;
01438 }
01439 
01440 /*
01441     @unimplemented
01442 */
01443 KSDDKAPI
01444 NTSTATUS
01445 NTAPI
01446 KsStreamPointerLock(
01447     IN PKSSTREAM_POINTER StreamPointer)
01448 {
01449     UNIMPLEMENTED
01450     return STATUS_UNSUCCESSFUL;
01451 }
01452 
01453 /*
01454     @unimplemented
01455 */
01456 KSDDKAPI
01457 VOID
01458 NTAPI
01459 KsStreamPointerUnlock(
01460     IN PKSSTREAM_POINTER StreamPointer,
01461     IN BOOLEAN Eject)
01462 {
01463     PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01464 
01465     DPRINT("KsStreamPointerUnlock StreamPointer %pEject %lu\n", StreamPointer, Eject);
01466 
01467     Pointer->Irp = NULL;
01468 }
01469 
01470 /*
01471     @unimplemented
01472 */
01473 KSDDKAPI
01474 VOID
01475 NTAPI
01476 KsStreamPointerAdvanceOffsetsAndUnlock(
01477     IN PKSSTREAM_POINTER StreamPointer,
01478     IN ULONG InUsed,
01479     IN ULONG OutUsed,
01480     IN BOOLEAN Eject)
01481 {
01482     DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
01483     DbgBreakPoint();
01484     UNIMPLEMENTED
01485 }
01486 
01487 /*
01488     @implemented
01489 */
01490 KSDDKAPI
01491 VOID
01492 NTAPI
01493 KsStreamPointerDelete(
01494     IN PKSSTREAM_POINTER StreamPointer)
01495 {
01496     IKsPinImpl * This;
01497     PKSISTREAM_POINTER Cur, Last;
01498     PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01499 
01500     DPRINT("KsStreamPointerDelete %p\n", Pointer);
01501 DbgBreakPoint();
01502     This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
01503 
01504     /* point to first stream pointer */
01505     Last = NULL;
01506     Cur = This->ClonedStreamPointer;
01507 
01508     while(Cur != Pointer && Cur)
01509     {
01510         Last = Cur;
01511         /* iterate to next cloned pointer */
01512         Cur = Cur->Next;
01513     }
01514 
01515     if (!Cur)
01516     {
01517         /* you naughty driver */
01518         return;
01519     }
01520 
01521     if (!Last)
01522     {
01523         /* remove first cloned pointer */
01524         This->ClonedStreamPointer = Pointer->Next;
01525     }
01526     else
01527     {
01528         Last->Next = Pointer->Next;
01529     }
01530 
01531     /* FIXME make sure no timeouts are pending */
01532     FreeItem(Pointer);
01533 }
01534 
01535 /*
01536     @implemented
01537 */
01538 KSDDKAPI
01539 NTSTATUS
01540 NTAPI
01541 KsStreamPointerClone(
01542     IN PKSSTREAM_POINTER StreamPointer,
01543     IN PFNKSSTREAMPOINTER CancelCallback OPTIONAL,
01544     IN ULONG ContextSize,
01545     OUT PKSSTREAM_POINTER* CloneStreamPointer)
01546 {
01547     IKsPinImpl * This;
01548     PKSISTREAM_POINTER CurFrame;
01549     PKSISTREAM_POINTER NewFrame;
01550     ULONG_PTR RefCount;
01551     NTSTATUS Status;
01552     ULONG Size;
01553 
01554     DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer);
01555 
01556     /* get stream pointer */
01557     CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01558 
01559     /* calculate context size */
01560     Size = sizeof(KSISTREAM_POINTER) + ContextSize;
01561 
01562     /* allocate new stream pointer */
01563     NewFrame = (PKSISTREAM_POINTER)AllocateItem(NonPagedPool, Size);
01564 
01565     if (!NewFrame)
01566         return STATUS_INSUFFICIENT_RESOURCES;
01567 
01568     /* get current irp stack location */
01569     RefCount = (ULONG_PTR)CurFrame->Irp->Tail.Overlay.DriverContext[0];
01570 
01571     /* increment reference count */
01572     RefCount++;
01573     CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
01574 
01575     /* copy stream pointer */
01576     RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER));
01577 
01578     /* locate pin */
01579     This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
01580 
01581     /* prepare stream header in case required */
01582     if (CurFrame->StreamPointer.Offset->Remaining == 0)
01583     {
01584         Status = IKsPin_PrepareStreamHeader(This, NewFrame);
01585         if (!NT_SUCCESS(Status))
01586         {
01587             FreeItem(NewFrame);
01588             return STATUS_DEVICE_NOT_READY;
01589         }
01590     }
01591 
01592     if (ContextSize)
01593         NewFrame->StreamPointer.Context = (NewFrame + 1);
01594 
01595 
01596     if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
01597         NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetIn;
01598     else
01599         NewFrame->StreamPointer.Offset = &NewFrame->StreamPointer.OffsetOut;
01600 
01601 
01602 
01603     NewFrame->StreamPointer.Pin = &This->Pin;
01604 
01605     ASSERT(NewFrame->StreamPointer.Pin);
01606     ASSERT(NewFrame->StreamPointer.Context);
01607     ASSERT(NewFrame->StreamPointer.Offset);
01608     ASSERT(NewFrame->StreamPointer.StreamHeader);
01609 
01610     /* store result */
01611     *CloneStreamPointer = &NewFrame->StreamPointer;
01612 
01613     DPRINT("KsStreamPointerClone CloneStreamPointer %p\n", *CloneStreamPointer);
01614 
01615     return STATUS_SUCCESS;
01616 }
01617 
01618 /*
01619     @implemented
01620 */
01621 KSDDKAPI
01622 NTSTATUS
01623 NTAPI
01624 KsStreamPointerAdvanceOffsets(
01625     IN PKSSTREAM_POINTER StreamPointer,
01626     IN ULONG InUsed,
01627     IN ULONG OutUsed,
01628     IN BOOLEAN Eject)
01629 {
01630     PKSISTREAM_POINTER CurFrame;
01631     IKsPinImpl * This;
01632     NTSTATUS Status;
01633 
01634     DPRINT("KsStreamPointerAdvanceOffsets StreamPointer %p InUsed %lu OutUsed %lu Eject %lu\n", StreamPointer, InUsed, OutUsed, Eject);
01635 
01636     /* get stream pointer */
01637     CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01638 
01639     /* locate pin */
01640     This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
01641 
01642     /* TODO */
01643     ASSERT(InUsed == 0);
01644     ASSERT(Eject == 0);
01645     ASSERT(OutUsed);
01646 
01647     DPRINT("KsStreamPointerAdvanceOffsets Offset %lu Length %lu NewOffset %lu Remaining %lu LeadingEdge %p DataUsed %lu\n", CurFrame->Offset, CurFrame->Length, CurFrame->Offset + OutUsed,
01648 CurFrame->StreamPointer.OffsetOut.Remaining, &This->LeadingEdgeStreamPointer.StreamPointer, CurFrame->StreamPointer.StreamHeader->DataUsed);
01649 DbgBreakPoint();
01650 
01651     if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
01652     {
01653         ASSERT(CurFrame->StreamPointer.OffsetIn.Remaining >= InUsed);
01654         CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed;
01655         CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed);
01656     }
01657     else
01658     {
01659         if (!CurFrame->StreamPointer.OffsetOut.Remaining)
01660         {
01661             Status = IKsPin_PrepareStreamHeader(This, CurFrame);
01662             if (!NT_SUCCESS(Status))
01663             {
01664                 return STATUS_DEVICE_NOT_READY;
01665             }
01666         }
01667         else
01668         {
01669             ASSERT(CurFrame->StreamPointer.OffsetOut.Remaining >= OutUsed);
01670             CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed;
01671             CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed);
01672         }
01673     }
01674 
01675     return STATUS_SUCCESS;
01676 }
01677 
01678 /*
01679     @unimplemented
01680 */
01681 KSDDKAPI
01682 NTSTATUS
01683 NTAPI
01684 KsStreamPointerAdvance(
01685     IN PKSSTREAM_POINTER StreamPointer)
01686 {
01687     UNIMPLEMENTED
01688     DbgBreakPoint();
01689     return STATUS_NOT_IMPLEMENTED;
01690 }
01691 
01692 /*
01693     @unimplemented
01694 */
01695 KSDDKAPI
01696 PMDL
01697 NTAPI
01698 KsStreamPointerGetMdl(
01699     IN PKSSTREAM_POINTER StreamPointer)
01700 {
01701     UNIMPLEMENTED
01702     return NULL;
01703 }
01704 
01705 /*
01706     @unimplemented
01707 */
01708 KSDDKAPI
01709 PIRP
01710 NTAPI
01711 KsStreamPointerGetIrp(
01712     IN PKSSTREAM_POINTER StreamPointer,
01713     OUT PBOOLEAN FirstFrameInIrp OPTIONAL,
01714     OUT PBOOLEAN LastFrameInIrp OPTIONAL)
01715 {
01716     UNIMPLEMENTED
01717     return NULL;
01718 }
01719 
01720 /*
01721     @implemented
01722 */
01723 KSDDKAPI
01724 VOID
01725 NTAPI
01726 KsStreamPointerScheduleTimeout(
01727     IN PKSSTREAM_POINTER StreamPointer,
01728     IN PFNKSSTREAMPOINTER Callback,
01729     IN ULONGLONG Interval)
01730 {
01731     LARGE_INTEGER DueTime;
01732     PKSISTREAM_POINTER Pointer;
01733 
01734     /* get stream pointer */
01735     Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01736 
01737     /* setup timer callback */
01738     Pointer->Callback = Callback;
01739 
01740     /* setup expiration */
01741     DueTime.QuadPart = (LONGLONG)Interval;
01742 
01743     /* setup the timer */
01744     KeSetTimer(&Pointer->Timer, DueTime, &Pointer->TimerDpc);
01745 
01746 }
01747 
01748 /*
01749     @implemented
01750 */
01751 KSDDKAPI
01752 VOID
01753 NTAPI
01754 KsStreamPointerCancelTimeout(
01755     IN PKSSTREAM_POINTER StreamPointer)
01756 {
01757     PKSISTREAM_POINTER Pointer;
01758 
01759     /* get stream pointer */
01760     Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01761 
01762     KeCancelTimer(&Pointer->Timer);
01763 
01764 }
01765 
01766 /*
01767     @implemented
01768 */
01769 KSDDKAPI
01770 PKSSTREAM_POINTER
01771 NTAPI
01772 KsPinGetFirstCloneStreamPointer(
01773     IN PKSPIN Pin)
01774 {
01775     IKsPinImpl * This;
01776 
01777     DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
01778 
01779     This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
01780 
01781     if (!This->ClonedStreamPointer)
01782         return NULL;
01783 
01784     /* return first cloned stream pointer */
01785     return &This->ClonedStreamPointer->StreamPointer;
01786 }
01787 
01788 /*
01789     @implemented
01790 */
01791 KSDDKAPI
01792 PKSSTREAM_POINTER
01793 NTAPI
01794 KsStreamPointerGetNextClone(
01795     IN PKSSTREAM_POINTER StreamPointer)
01796 {
01797     PKSISTREAM_POINTER Pointer;
01798 
01799     DPRINT("KsStreamPointerGetNextClone\n");
01800 DbgBreakPoint();
01801     /* get stream pointer */
01802     Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
01803 
01804     /* is there a another cloned stream pointer */
01805     if (!Pointer->Next)
01806         return NULL;
01807 
01808     /* return next stream pointer */
01809     return &Pointer->Next->StreamPointer;
01810 }
01811 
01812 VOID
01813 NTAPI
01814 IKsPin_PinCentricWorker(
01815     IN PVOID Parameter)
01816 {
01817     NTSTATUS Status;
01818     IKsPinImpl * This = (IKsPinImpl*)Parameter;
01819 
01820     DPRINT("IKsPin_PinCentricWorker\n");
01821 
01822     /* sanity checks */
01823     ASSERT(This);
01824     ASSERT(This->Pin.Descriptor);
01825     ASSERT(This->Pin.Descriptor->Dispatch);
01826     ASSERT(This->Pin.Descriptor->Dispatch->Process);
01827     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
01828     ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
01829     ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_GENERATE_MAPPINGS));
01830 
01831     do
01832     {
01833         DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n");
01834 
01835         Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
01836         DPRINT("IKsPin_PinCentricWorker Status %lx, Offset %lu Length %lu\n", Status,
01837                This->LeadingEdgeStreamPointer.Offset,
01838                This->LeadingEdgeStreamPointer.Length);
01839         break;
01840 
01841     }while(This->IrpCount);
01842 }
01843 
01844 
01845 NTSTATUS
01846 NTAPI
01847 IKsPin_DispatchKsStream(
01848     PDEVICE_OBJECT DeviceObject,
01849     PIRP Irp,
01850     IKsPinImpl * This)
01851 {
01852     PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
01853     PKSSTREAM_HEADER Header;
01854     ULONG NumHeaders;
01855     PKSFILTER Filter;
01856     PIO_STACK_LOCATION IoStack;
01857     NTSTATUS Status = STATUS_SUCCESS;
01858 
01859     DPRINT("IKsPin_DispatchKsStream\n");
01860 
01861     /* FIXME handle reset states */
01862     ASSERT(This->Pin.ResetState == KSRESET_END);
01863 
01864     /* get current stack location */
01865     IoStack = IoGetCurrentIrpStackLocation(Irp);
01866 
01867     /* probe stream pointer */
01868     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
01869         Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
01870     else
01871         Status = KsProbeStreamIrp(Irp, KSSTREAM_READ  | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
01872 
01873     if (!NT_SUCCESS(Status))
01874     {
01875         DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
01876 
01877         Irp->IoStatus.Status = Status;
01878         CompleteRequest(Irp, IO_NO_INCREMENT);
01879         return Status;
01880     }
01881 
01882     if (Irp->RequestorMode == UserMode)
01883         Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
01884     else
01885         Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
01886 
01887     if (!Header)
01888     {
01889         DPRINT("NoHeader Canceling Irp %p\n", Irp);
01890         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
01891         CompleteRequest(Irp, IO_NO_INCREMENT);
01892         return Status;
01893     }
01894 
01895     /* calculate num headers */
01896     NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
01897 
01898     /* assume headers of same length */
01899     ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
01900 
01901     /* FIXME support multiple stream headers */
01902     ASSERT(NumHeaders == 1);
01903 
01904     if (Irp->RequestorMode == UserMode)
01905     {
01906         /* prepare header */
01907         ASSERT(Irp->MdlAddress);
01908         Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
01909 
01910         if (!Header->Data)
01911         {
01912             DPRINT("NoHeader->Data Canceling Irp %p\n", Irp);
01913             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
01914             CompleteRequest(Irp, IO_NO_INCREMENT);
01915             return Status;
01916         }
01917 
01918     }
01919 
01920 
01921 
01922     if (This->Pin.Descriptor->Dispatch->Process)
01923     {
01924         /* it is a pin centric avstream */
01925 
01926         /* mark irp as pending */
01927         IoMarkIrpPending(Irp);
01928 
01929         /* add irp to cancelable queue */
01930         KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
01931 
01932         /* sanity checks */
01933         ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
01934         ASSERT(This->PinWorker);
01935 
01936         InterlockedIncrement(&This->IrpCount);
01937 
01938         DPRINT("IKsPin_DispatchKsStream IrpCount %lu\n", This->IrpCount);
01939 
01940         /* start the processing loop */
01941         KsIncrementCountedWorker(This->PinWorker);
01942 
01943         Status = STATUS_PENDING;
01944     }
01945     else
01946     {
01947         /* filter-centric avstream */
01948         ASSERT(This->Filter);
01949 
01950         ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
01951         Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
01952 
01953         ASSERT(ProcessPinIndex);
01954         ASSERT(Filter);
01955         ASSERT(Filter->Descriptor);
01956         ASSERT(Filter->Descriptor->Dispatch);
01957 
01958         if (!Filter->Descriptor->Dispatch->Process)
01959         {
01960             /* invalid device request */
01961             DPRINT("Filter Centric Processing No Process Routine\n");
01962             Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
01963             CompleteRequest(Irp, IO_NO_INCREMENT);
01964             return STATUS_UNSUCCESSFUL;
01965         }
01966 
01967         /* mark irp as pending */
01968         IoMarkIrpPending(Irp);
01969 
01970         /* add irp to cancelable queue */
01971         KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
01972 
01973         Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
01974 
01975         DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
01976 
01977     }
01978 
01979     return Status;
01980 }
01981 
01982 NTSTATUS
01983 NTAPI
01984 IKsPin_DispatchDeviceIoControl(
01985     IN PDEVICE_OBJECT DeviceObject,
01986     IN PIRP Irp)
01987 {
01988     PIO_STACK_LOCATION IoStack;
01989     PKSIOBJECT_HEADER ObjectHeader;
01990     IKsPinImpl * This;
01991     NTSTATUS Status;
01992     UNICODE_STRING GuidString;
01993     PKSPROPERTY Property;
01994     ULONG SetCount = 0;
01995 
01996     /* get current irp stack */
01997     IoStack = IoGetCurrentIrpStackLocation(Irp);
01998 
01999     /* sanity check */
02000     ASSERT(IoStack->FileObject);
02001     ASSERT(IoStack->FileObject->FsContext2);
02002 
02003     /* get the object header */
02004     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
02005 
02006     /* locate ks pin implemention from KSPIN offset */
02007     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
02008 
02009     /* current irp stack */
02010     IoStack = IoGetCurrentIrpStackLocation(Irp);
02011 
02012     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM ||
02013         IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
02014     {
02015         /* handle ks stream packets */
02016         return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
02017     }
02018 
02019     /* get property from input buffer */
02020     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
02021 
02022     /* sanity check */
02023     ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
02024     ASSERT(This->Pin.Descriptor->AutomationTable);
02025 
02026     RtlStringFromGUID(&Property->Set, &GuidString);
02027     DPRINT("IKsPin_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
02028     RtlFreeUnicodeString(&GuidString);
02029 
02030 
02031     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
02032     {
02033         const KSMETHOD_SET *MethodSet = NULL;
02034         ULONG MethodItemSize = 0;
02035 
02036         /* check if the driver supports method sets */
02037         if (This->Pin.Descriptor->AutomationTable->MethodSetsCount)
02038         {
02039             SetCount = This->Pin.Descriptor->AutomationTable->MethodSetsCount;
02040             MethodSet = This->Pin.Descriptor->AutomationTable->MethodSets;
02041             MethodItemSize = This->Pin.Descriptor->AutomationTable->MethodItemSize;
02042         }
02043 
02044         /* call method set handler */
02045         Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
02046     }
02047     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
02048     {
02049         const KSPROPERTY_SET *PropertySet = NULL;
02050         ULONG PropertyItemSize = 0;
02051 
02052         /* check if the driver supports method sets */
02053         if (This->Pin.Descriptor->AutomationTable->PropertySetsCount)
02054         {
02055             SetCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
02056             PropertySet = This->Pin.Descriptor->AutomationTable->PropertySets;
02057             PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
02058         }
02059 
02060         /* needed for our property handlers */
02061         KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
02062 
02063         /* call property handler */
02064         Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
02065     }
02066     else
02067     {
02068         /* sanity check */
02069         ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
02070                IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
02071 
02072         if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
02073         {
02074             /* call enable event handlers */
02075             Status = KspEnableEvent(Irp,
02076                                     This->Pin.Descriptor->AutomationTable->EventSetsCount,
02077                                     (PKSEVENT_SET)This->Pin.Descriptor->AutomationTable->EventSets,
02078                                     &This->BasicHeader.EventList,
02079                                     KSEVENTS_SPINLOCK,
02080                                     (PVOID)&This->BasicHeader.EventListLock,
02081                                     NULL,
02082                                     This->Pin.Descriptor->AutomationTable->EventItemSize);
02083         }
02084         else
02085         {
02086             /* disable event handler */
02087             Status = KsDisableEvent(Irp, &This->BasicHeader.EventList, KSEVENTS_SPINLOCK, &This->BasicHeader.EventListLock);
02088         }
02089     }
02090 
02091     RtlStringFromGUID(&Property->Set, &GuidString);
02092     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);
02093     RtlFreeUnicodeString(&GuidString);
02094 
02095     if (Status != STATUS_PENDING)
02096     {
02097         Irp->IoStatus.Status = Status;
02098         CompleteRequest(Irp, IO_NO_INCREMENT);
02099     }
02100 
02101     /* done */
02102     return Status;
02103 }
02104 
02105 NTSTATUS
02106 NTAPI
02107 IKsPin_Close(
02108     IN PDEVICE_OBJECT DeviceObject,
02109     IN PIRP Irp)
02110 {
02111     PIO_STACK_LOCATION IoStack;
02112     PKSIOBJECT_HEADER ObjectHeader;
02113     IKsPinImpl * This;
02114     NTSTATUS Status = STATUS_SUCCESS;
02115 
02116     /* get current irp stack */
02117     IoStack = IoGetCurrentIrpStackLocation(Irp);
02118 
02119     /* sanity check */
02120     ASSERT(IoStack->FileObject);
02121     ASSERT(IoStack->FileObject->FsContext2);
02122 
02123     /* get the object header */
02124     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
02125 
02126     /* locate ks pin implemention fro KSPIN offset */
02127     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
02128 
02129     if (This->Pin.Descriptor->Dispatch->Close)
02130     {
02131         /* call pin close routine */
02132         Status = This->Pin.Descriptor->Dispatch->Close(&This->Pin, Irp);
02133 
02134         if (!NT_SUCCESS(Status))
02135         {
02136             /* abort closing */
02137             Irp->IoStatus.Status = Status;
02138             CompleteRequest(Irp, IO_NO_INCREMENT);
02139             return Status;
02140         }
02141 
02142         /* remove pin from filter pin list and decrement reference count */
02143         IKsFilter_RemovePin(This->Filter->lpVtbl->GetStruct(This->Filter), &This->Pin);
02144 
02145         if (Status != STATUS_PENDING)
02146         {
02147             Irp->IoStatus.Status = Status;
02148             CompleteRequest(Irp, IO_NO_INCREMENT);
02149             return Status;
02150         }
02151     }
02152 
02153     return Status;
02154 }
02155 
02156 NTSTATUS
02157 NTAPI
02158 IKsPin_DispatchCreateAllocator(
02159     IN PDEVICE_OBJECT DeviceObject,
02160     IN PIRP Irp)
02161 {
02162     UNIMPLEMENTED;
02163 
02164     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
02165     CompleteRequest(Irp, IO_NO_INCREMENT);
02166     return STATUS_NOT_IMPLEMENTED;
02167 }
02168 
02169 NTSTATUS
02170 NTAPI
02171 IKsPin_DispatchCreateClock(
02172     IN PDEVICE_OBJECT DeviceObject,
02173     IN PIRP Irp)
02174 {
02175     PKSPIN Pin;
02176     NTSTATUS Status = STATUS_SUCCESS;
02177     IKsPinImpl * This;
02178     KSRESOLUTION Resolution;
02179     PKSRESOLUTION pResolution = NULL;
02180     PKSOBJECT_CREATE_ITEM CreateItem;
02181 
02182     DPRINT("IKsPin_DispatchCreateClock\n");
02183 
02184     /* get the create item */
02185     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
02186 
02187     /* sanity check */
02188     ASSERT(CreateItem);
02189 
02190     /* get the pin object */
02191     Pin = (PKSPIN)CreateItem->Context;
02192 
02193     /* sanity check */
02194     ASSERT(Pin);
02195 
02196     /* locate ks pin implemention fro KSPIN offset */
02197     This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
02198 
02199     /* sanity check */
02200     ASSERT(This->BasicHeader.Type == KsObjectTypePin);
02201     ASSERT(This->BasicHeader.ControlMutex);
02202 
02203     /* acquire control mutex */
02204     KsAcquireControl(Pin);
02205 
02206     if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
02207         This->Pin.Descriptor->Dispatch) ||
02208         (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
02209     {
02210         if (!This->DefaultClock)
02211         {
02212             if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
02213             {
02214                 if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
02215                 {
02216                    This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
02217                    pResolution = &Resolution;
02218                 }
02219 
02220                 Status = KsAllocateDefaultClockEx(&This->DefaultClock, 
02221                                                   (PVOID)&This->Pin,
02222                                                   (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
02223                                                   (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
02224                                                   (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
02225                                                   pResolution,
02226                                                   0);
02227             }
02228             else
02229             {
02230                 Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
02231             }
02232         }
02233 
02234         if (NT_SUCCESS(Status))
02235         {
02236             Status = KsCreateDefaultClock(Irp, This->DefaultClock);
02237         }
02238     }
02239 
02240     DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
02241 
02242     /* release control mutex */
02243     KsReleaseControl(Pin);
02244 
02245     /* done */
02246     Irp->IoStatus.Status = Status;
02247     CompleteRequest(Irp, IO_NO_INCREMENT);
02248     return Status;
02249 }
02250 
02251 NTSTATUS
02252 NTAPI
02253 IKsPin_DispatchCreateNode(
02254     IN PDEVICE_OBJECT DeviceObject,
02255     IN PIRP Irp)
02256 {
02257     UNIMPLEMENTED;
02258 
02259     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
02260     CompleteRequest(Irp, IO_NO_INCREMENT);
02261     return STATUS_NOT_IMPLEMENTED;
02262 }
02263 
02264 static KSDISPATCH_TABLE PinDispatchTable = 
02265 {
02266     IKsPin_DispatchDeviceIoControl,
02267     KsDispatchInvalidDeviceRequest,
02268     KsDispatchInvalidDeviceRequest,
02269     KsDispatchInvalidDeviceRequest,
02270     IKsPin_Close,
02271     KsDispatchQuerySecurity,
02272     KsDispatchSetSecurity,
02273     KsDispatchFastIoDeviceControlFailure,
02274     KsDispatchFastReadFailure,
02275     KsDispatchFastReadFailure
02276 };
02277 
02278 NTSTATUS
02279 KspCreatePin(
02280     IN PDEVICE_OBJECT DeviceObject,
02281     IN PIRP Irp,
02282     IN PKSDEVICE KsDevice,
02283     IN IKsFilterFactory * FilterFactory,
02284     IN IKsFilter* Filter,
02285     IN PKSPIN_CONNECT Connect,
02286     IN KSPIN_DESCRIPTOR_EX* Descriptor)
02287 {
02288     IKsPinImpl * This;
02289     PIO_STACK_LOCATION IoStack;
02290     IKsDevice * Device;
02291     PDEVICE_EXTENSION DeviceExtension;
02292     PKSOBJECT_CREATE_ITEM CreateItem;
02293     NTSTATUS Status;
02294     PKSDATAFORMAT DataFormat;
02295     PKSBASIC_HEADER BasicHeader;
02296     ULONG Index;
02297     ULONG FrameSize = 0;
02298     ULONG NumFrames = 0;
02299     KSAUTOMATION_TABLE AutomationTable;
02300 
02301     /* sanity checks */
02302     ASSERT(Descriptor->Dispatch);
02303 
02304     DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
02305 
02306 //Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
02307 //Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
02308 
02309     DPRINT("KspCreatePin Dataflow %lu\n", Descriptor->PinDescriptor.DataFlow);
02310     DPRINT("KspCreatePin Communication %lu\n", Descriptor->PinDescriptor.Communication);
02311     if (Descriptor->AllocatorFraming)
02312     {
02313         DPRINT("KspCreatePin CountItems %lu\n", Descriptor->AllocatorFraming->CountItems);
02314         DPRINT("KspCreatePin PinFlags %lx\n", Descriptor->AllocatorFraming->PinFlags);
02315         DPRINT("KspCreatePin OutputCompression RatioNumerator %lu RatioDenominator  %lu RatioConstantMargin %lu\n", Descriptor->AllocatorFraming->OutputCompression.RatioNumerator,
02316                Descriptor->AllocatorFraming->OutputCompression.RatioDenominator, Descriptor->AllocatorFraming->OutputCompression.RatioConstantMargin);
02317         DPRINT("KspCreatePin PinWeight %lx\n", Descriptor->AllocatorFraming->PinWeight);
02318 
02319         for(Index = 0; Index < Descriptor->AllocatorFraming->CountItems; Index++)
02320         {
02321             DPRINT("KspCreatePin Index %lu MemoryFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryFlags);
02322             DPRINT("KspCreatePin Index %lu BusFlags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].BusFlags);
02323             DPRINT("KspCreatePin Index %lu Flags %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Flags);
02324             DPRINT("KspCreatePin Index %lu Frames %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].Frames);
02325             DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment);
02326             DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight);
02327             DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize,
02328                    Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize, 
02329                    Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping);
02330 
02331             DPRINT("KspCreatePin Index %lu FramingRange  MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n", 
02332                    Index,
02333                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize,
02334                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize,
02335                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.Stepping,
02336                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.InPlaceWeight,
02337                    Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.NotInPlaceWeight);
02338 
02339            FrameSize = Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize;
02340            NumFrames = Descriptor->AllocatorFraming->FramingItem[Index].Frames;
02341         }
02342     }
02343 
02344      for (Index = 0; Index < Descriptor->PinDescriptor.DataRangesCount; Index++)
02345      {
02346          UNICODE_STRING GuidString;
02347          /* convert the guid to string */
02348          RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->MajorFormat, &GuidString);
02349          DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer);
02350          RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &GuidString);
02351          DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer);
02352          RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
02353          DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer);
02354          RtlStringFromGUID(&Descriptor->PinDescriptor.DataRanges[Index]->Specifier, &GuidString);
02355          DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index,
02356                 Descriptor->PinDescriptor.DataRanges[Index]->FormatSize, Descriptor->PinDescriptor.DataRanges[Index]->Flags, Descriptor->PinDescriptor.DataRanges[Index]->SampleSize, Descriptor->PinDescriptor.DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT));
02357 
02358          if (IsEqualGUIDAligned(&Descriptor->PinDescriptor.DataRanges[Index]->SubFormat, &KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT))
02359          {
02360              PKS_DATARANGE_BDA_TRANSPORT Transport = (PKS_DATARANGE_BDA_TRANSPORT)&Descriptor->PinDescriptor.DataRanges[Index];
02361              DPRINT("KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT AvgTimePerFrame %I64u ulcbPhyiscalFrame %lu ulcbPhyiscalFrameAlignment %lu ulcbPhyiscalPacket %lu\n", Transport->BdaTransportInfo.AvgTimePerFrame, Transport->BdaTransportInfo.ulcbPhyiscalFrame,
02362                     Transport->BdaTransportInfo.ulcbPhyiscalFrameAlignment, Transport->BdaTransportInfo.ulcbPhyiscalPacket);
02363          }
02364     }
02365     if (!FrameSize)
02366     {
02367         /* default to 50 * 188 (MPEG2 TS packet size) */
02368         FrameSize = 9400;
02369     }
02370 
02371     if (!NumFrames)
02372     {
02373         NumFrames = 8;
02374     }
02375 
02376     /* get current irp stack */
02377     IoStack = IoGetCurrentIrpStackLocation(Irp);
02378 
02379     /* get device extension */
02380     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
02381 
02382     /* get ks device interface */
02383     Device = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
02384 
02385     /* first allocate pin ctx */
02386     This = AllocateItem(NonPagedPool, sizeof(IKsPinImpl));
02387     if (!This)
02388     {
02389         /* not enough memory */
02390         return STATUS_INSUFFICIENT_RESOURCES;
02391     }
02392 
02393     /* allocate create item */
02394     CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 3);
02395     if (!CreateItem)
02396     {
02397         /* not enough memory */
02398         FreeItem(This);
02399         DPRINT("KspCreatePin OutOfMemory\n");
02400         return STATUS_INSUFFICIENT_RESOURCES;
02401     }
02402 
02403     /* initialize basic header */
02404     This->BasicHeader.KsDevice = KsDevice;
02405     This->BasicHeader.Type = KsObjectTypePin;
02406     This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
02407     This->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsPin;
02408     InitializeListHead(&This->BasicHeader.EventList);
02409     KeInitializeSpinLock(&This->BasicHeader.EventListLock);
02410 
02411     ASSERT(This->BasicHeader.Parent.KsFilter);
02412 
02413     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
02414 
02415     This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
02416     ASSERT(This->BasicHeader.ControlMutex);
02417 
02418     InitializeListHead(&This->BasicHeader.EventList);
02419     KeInitializeSpinLock(&This->BasicHeader.EventListLock);
02420 
02421     /* initialize pin */
02422     This->FrameSize = FrameSize;
02423     This->NumFrames = NumFrames;
02424     This->lpVtblReferenceClock = &vt_ReferenceClock;
02425     This->ref = 1;
02426     This->FileObject = IoStack->FileObject;
02427     This->Filter = Filter;
02428     KeInitializeMutex(&This->ProcessingMutex, 0);
02429     InitializeListHead(&This->IrpList);
02430     KeInitializeSpinLock(&This->IrpListLock);
02431 
02432     /* allocate object bag */
02433     This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
02434     if (!This->Pin.Bag)
02435     {
02436         /* not enough memory */
02437         FreeItem(This);
02438         FreeItem(CreateItem);
02439         return STATUS_INSUFFICIENT_RESOURCES;
02440     }
02441 
02442     /* initialize object bag */
02443     Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
02444 
02445     /* allocate pin descriptor */
02446     This->Pin.Descriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
02447     if (!This->Pin.Descriptor)
02448     {
02449         /* not enough memory */
02450         KsFreeObjectBag(This->Pin.Bag);
02451         FreeItem(This);
02452         FreeItem(CreateItem);
02453         return STATUS_INSUFFICIENT_RESOURCES;
02454     }
02455 
02456     /* copy pin descriptor */
02457     RtlMoveMemory((PVOID)This->Pin.Descriptor, Descriptor, sizeof(KSPIN_DESCRIPTOR_EX));
02458 
02459     /* initialize automation table */
02460     RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
02461 
02462     AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
02463     AutomationTable.PropertySets = PinPropertySet;
02464     AutomationTable.PropertySetsCount = sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET);
02465 
02466     /* merge in pin property sets */
02467     Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Pin.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)Descriptor->AutomationTable, &AutomationTable, This->Pin.Bag);
02468 
02469     if (!NT_SUCCESS(Status))
02470     {
02471         /* not enough memory */
02472         KsFreeObjectBag(This->Pin.Bag);
02473         FreeItem(This);
02474         FreeItem(CreateItem);
02475         return Status;
02476     }
02477 
02478     /* get format */
02479     DataFormat = (PKSDATAFORMAT)(Connect + 1);
02480 
02481     /* initialize pin descriptor */
02482     This->Pin.Context = NULL;
02483     This->Pin.Id = Connect->PinId;
02484     This->Pin.Communication = Descriptor->PinDescriptor.Communication;
02485     This->Pin.ConnectionIsExternal = FALSE; //FIXME
02486     RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
02487     RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
02488     RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
02489 
02490     /* allocate format */
02491     Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
02492     if (!NT_SUCCESS(Status))
02493     {
02494         /* failed to allocate format */
02495         KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
02496         FreeItem(This);
02497         FreeItem(CreateItem);
02498         return STATUS_INSUFFICIENT_RESOURCES;
02499     }
02500 
02501     /* copy format */
02502     RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
02503 
02504     This->Pin.AttributeList = NULL; //FIXME
02505     This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
02506     This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
02507     This->Pin.DeviceState = KSSTATE_STOP;
02508     This->Pin.ResetState = KSRESET_END;
02509     This->Pin.ClientState = KSSTATE_STOP;
02510 
02511     /* intialize allocator create item */
02512     CreateItem[0].Context = (PVOID)&This->Pin;
02513     CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
02514     CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
02515     RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
02516 
02517     /* intialize clock create item */
02518     CreateItem[1].Context = (PVOID)&This->Pin;
02519     CreateItem[1].Create = IKsPin_DispatchCreateClock;
02520     CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
02521     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
02522 
02523     /* intialize topology node create item */
02524     CreateItem[2].Context = (PVOID)&This->Pin;
02525     CreateItem[2].Create = IKsPin_DispatchCreateNode;
02526     CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
02527     RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
02528 
02529     /* now allocate object header */
02530     Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&This->ObjectHeader, 3, CreateItem, Irp, &PinDispatchTable);
02531     if (!NT_SUCCESS(Status))
02532     {
02533         /* failed to create object header */
02534         DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
02535         KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
02536         FreeItem(This);
02537         FreeItem(CreateItem);
02538 
02539         /* return failure code */
02540         return Status;
02541     }
02542 
02543      /* add extra info to object header */
02544     This->ObjectHeader->Type = KsObjectTypePin;
02545     This->ObjectHeader->Unknown = (PUNKNOWN)&This->BasicHeader.OuterUnknown;
02546     This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
02547 
02548     if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
02549     {
02550         /* the pin is part of filter-centric processing filter
02551          * add process pin to filter
02552          */
02553         This->ProcessPin.BytesAvailable = 0;
02554         This->ProcessPin.BytesUsed = 0;
02555         This->ProcessPin.CopySource = NULL;
02556         This->ProcessPin.Data = NULL;
02557         This->ProcessPin.DelegateBranch = NULL;
02558         This->ProcessPin.Flags = 0;
02559         This->ProcessPin.InPlaceCounterpart = NULL;
02560         This->ProcessPin.Pin = &This->Pin;
02561         This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)&This->LeadingEdgeStreamPointer.StreamPointer;
02562         This->ProcessPin.Terminate = FALSE;
02563 
02564         Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
02565         DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
02566 
02567         if (!NT_SUCCESS(Status))
02568         {
02569             /* failed to add process pin */
02570             KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
02571             KsFreeObjectHeader(&This->ObjectHeader);
02572             FreeItem(This);
02573             FreeItem(CreateItem);
02574             /* return failure code */
02575             return Status;
02576         }
02577     }
02578     else if (Descriptor->Dispatch && Descriptor->Dispatch->Process)
02579     {
02580         /* pin centric processing filter */
02581 
02582         /* initialize work item */
02583         ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This);
02584 
02585         /* allocate counted work item */
02586         Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker);
02587 
02588         if (!NT_SUCCESS(Status))
02589         {
02590             DPRINT("Failed to register Worker %lx\n", Status);
02591             KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
02592             KsFreeObjectHeader(&This->ObjectHeader);
02593             FreeItem(This);
02594             FreeItem(CreateItem);
02595             return Status;
02596         }
02597 
02598         if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
02599             This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetIn;
02600         else
02601             This->LeadingEdgeStreamPointer.StreamPointer.Offset = &This->LeadingEdgeStreamPointer.StreamPointer.OffsetOut;
02602 
02603 
02604         KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE);
02605 
02606     }
02607 
02608     /* FIXME add pin instance to filter instance */
02609     IKsFilter_AddPin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
02610 
02611     if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
02612     {
02613         Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
02614         DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
02615     }
02616 
02617 
02618     /* does the driver have a pin dispatch */
02619     if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
02620     {
02621         /*  now inform the driver to create a new pin */
02622         Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
02623         DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
02624     }
02625 
02626 
02627     DPRINT("KspCreatePin Status %lx KsDevice %p\n", Status, KsDevice);
02628 
02629     if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
02630     {
02631         /* failed to create pin, release resources */
02632         IKsFilter_RemovePin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
02633         KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader);
02634         KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
02635         FreeItem(This);
02636 
02637         /* return failure code */
02638         return Status;
02639     }
02640 
02641     return Status;
02642 }

Generated on Sun May 27 2012 04:21:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.