[KS]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 28 Jan 2011 10:37:27 +0000 (10:37 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 28 Jan 2011 10:37:27 +0000 (10:37 +0000)
- Merge from audio branch
- Perform irp completion in dedicated function
- Move Software Bus function into own file
- Remove debugging code which caused crashes
- Partly implement IKsProcessingObject interface for filter
- Fix check in FindMatchingCreateItem function
- Implement software bus enumerator functions
[SWENUM]
- Implement SwDispatchPower, SwDispatchPower

svn path=/trunk/; revision=50531

18 files changed:
1  2 
reactos/drivers/ksfilter/directory.rbuild
reactos/drivers/ksfilter/ks/allocators.c
reactos/drivers/ksfilter/ks/api.c
reactos/drivers/ksfilter/ks/clocks.c
reactos/drivers/ksfilter/ks/device.c
reactos/drivers/ksfilter/ks/filter.c
reactos/drivers/ksfilter/ks/filterfactory.c
reactos/drivers/ksfilter/ks/irp.c
reactos/drivers/ksfilter/ks/ks.rbuild
reactos/drivers/ksfilter/ks/ksfunc.h
reactos/drivers/ksfilter/ks/ksiface.h
reactos/drivers/ksfilter/ks/kstypes.h
reactos/drivers/ksfilter/ks/misc.c
reactos/drivers/ksfilter/ks/pin.c
reactos/drivers/ksfilter/ks/priv.h
reactos/drivers/ksfilter/ks/swenum.c
reactos/drivers/ksfilter/swenum/swenum.c
reactos/drivers/ksfilter/swenum/swenum.rbuild

Simple merge
Simple merge
Simple merge
index 5f4a74b,0000000..1e6ebbf
mode 100644,000000..100644
--- /dev/null
@@@ -1,1815 -1,0 +1,2071 @@@
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Kernel Streaming
 + * FILE:            drivers/ksfilter/ks/filter.c
 + * PURPOSE:         KS IKsFilter interface functions
 + * PROGRAMMER:      Johannes Anderwald
 + */
 +
 +
 +#include "priv.h"
 +
 +typedef struct
 +{
 +    KSBASIC_HEADER Header;
 +    KSFILTER Filter;
 +
 +    IKsControlVtbl *lpVtblKsControl;
 +    IKsFilterFactory * FilterFactory;
++    IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
 +    LONG ref;
 +
 +    PKSIOBJECT_HEADER ObjectHeader;
 +    KSTOPOLOGY Topology;
 +    PKSFILTERFACTORY Factory;
 +    PFILE_OBJECT FileObject;
 +    KMUTEX ControlMutex;
 +    KMUTEX ProcessingMutex;
 +
++    PKSWORKER Worker;
++    WORK_QUEUE_ITEM WorkItem;
++    KSGATE Gate;
 +
 +    PFNKSFILTERPOWER Sleep;
 +    PFNKSFILTERPOWER Wake;
 +
 +    ULONG *PinInstanceCount;
 +    PKSPIN * FirstPin;
 +    PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
 +
 +}IKsFilterImpl;
 +
 +const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
 +const GUID IID_IKsFilter  = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
 +const GUID KSPROPSETID_Topology                = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 +const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
 +
 +VOID
 +IKsFilter_RemoveFilterFromFilterFactory(
 +    IKsFilterImpl * This,
 +    PKSFILTERFACTORY FilterFactory);
 +
 +NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
 +NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
 +
 +
 +DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler);
 +DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler);
 +
 +KSPROPERTY_SET FilterPropertySet[] =
 +{
 +    {
 +        &KSPROPSETID_Topology,
 +        sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
 +        (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
 +        0,
 +        NULL
 +    },
 +    {
 +        &KSPROPSETID_Pin,
 +        sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
 +        (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
 +        0,
 +        NULL
 +    }
 +};
 +
++NTSTATUS
++NTAPI
++IKsProcessingObject_fnQueryInterface(
++    IKsProcessingObject * iface,
++    IN  REFIID refiid,
++    OUT PVOID* Output)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
++    {
++        *Output = &This->Header.OuterUnknown;
++        _InterlockedIncrement(&This->ref);
++        return STATUS_SUCCESS;
++    }
++    return STATUS_UNSUCCESSFUL;
++}
++
++ULONG
++NTAPI
++IKsProcessingObject_fnAddRef(
++    IKsProcessingObject * iface)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    return InterlockedIncrement(&This->ref);
++}
++
++ULONG
++NTAPI
++IKsProcessingObject_fnRelease(
++    IKsProcessingObject * iface)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    InterlockedDecrement(&This->ref);
++
++    /* Return new reference count */
++    return This->ref;
++}
++
++VOID
++NTAPI
++IKsProcessingObject_fnProcessingObjectWork(
++    IKsProcessingObject * iface)
++{
++    NTSTATUS Status;
++    LARGE_INTEGER TimeOut;
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    DPRINT1("processing object\n");
++    /* first check if running at passive level */
++    if (KeGetCurrentIrql() == PASSIVE_LEVEL)
++    {
++        /* acquire processing mutex */
++        KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL);
++    }
++    else
++    {
++        /* dispatch level processing */
++        if (KeReadStateMutex(&This->ControlMutex) == 0)
++        {
++            /* some thread was faster */
++            DPRINT1("processing object too slow\n");
++            return;
++        }
++
++        /* acquire processing mutex */
++        TimeOut.QuadPart = 0LL;
++        Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut);
++
++        if (Status == STATUS_TIMEOUT)
++        {
++            /* some thread was faster */
++            DPRINT1("processing object too slow\n");
++            return;
++        }
++    }
++
++    do
++    {
++
++        /* check if the and-gate has been enabled again */
++        if (&This->Gate.Count != 0)
++        {
++            /* gate is open */
++            DPRINT1("processing object gate open\n");
++            break;
++        }
++
++        DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
++        ASSERT(0);
++
++    }while(TRUE);
++
++    /* release process mutex */
++    KeReleaseMutex(&This->ProcessingMutex, FALSE);
++}
++
++PKSGATE
++NTAPI
++IKsProcessingObject_fnGetAndGate(
++    IKsProcessingObject * iface)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    /* return and gate */
++    return &This->Gate;
++}
++
++VOID
++NTAPI
++IKsProcessingObject_fnProcess(
++    IKsProcessingObject * iface,
++    IN BOOLEAN Asynchronous)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    /* should the action be asynchronous */
++    if (Asynchronous)
++    {
++        /* queue work item */
++        KsQueueWorkItem(This->Worker, &This->WorkItem);
++DPRINT1("queueing\n");
++        /* done */
++        return;
++    }
++
++    /* does the filter require explicit deferred processing */
++    if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) && 
++         KeGetCurrentIrql() > PASSIVE_LEVEL)
++    {
++        /* queue work item */
++        KsQueueWorkItem(This->Worker, &This->WorkItem);
++DPRINT1("queueing\n");
++        /* done */
++        return;
++    }
++DPRINT1("invoke\n");
++    /* call worker routine directly */
++    iface->lpVtbl->ProcessingObjectWork(iface);
++}
++
++VOID
++NTAPI
++IKsProcessingObject_fnReset(
++    IKsProcessingObject * iface)
++{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
++
++    /* acquire processing mutex */
++    KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
++
++    /* check if the filter supports dispatch routines */
++    if (This->Filter.Descriptor->Dispatch)
++    {
++        /* has the filter a reset routine */
++        if (This->Filter.Descriptor->Dispatch->Reset)
++        {
++            /* reset filter */
++            This->Filter.Descriptor->Dispatch->Reset(&This->Filter);
++        }
++    }
++
++    /* release process mutex */
++    KeReleaseMutex(&This->ProcessingMutex, FALSE);
++}
++
++VOID
++NTAPI
++IKsProcessingObject_fnTriggerNotification(
++    IKsProcessingObject * iface)
++{
++
++}
++
++static IKsProcessingObjectVtbl vt_IKsProcessingObject =
++{
++    IKsProcessingObject_fnQueryInterface,
++    IKsProcessingObject_fnAddRef,
++    IKsProcessingObject_fnRelease,
++    IKsProcessingObject_fnProcessingObjectWork,
++    IKsProcessingObject_fnGetAndGate,
++    IKsProcessingObject_fnProcess,
++    IKsProcessingObject_fnReset,
++    IKsProcessingObject_fnTriggerNotification
++};
++
++
++//---------------------------------------------------------------------------------------------------------
 +NTSTATUS
 +NTAPI
 +IKsControl_fnQueryInterface(
 +    IKsControl * iface,
 +    IN  REFIID refiid,
 +    OUT PVOID* Output)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
 +    {
 +        *Output = &This->Header.OuterUnknown;
 +        _InterlockedIncrement(&This->ref);
 +        return STATUS_SUCCESS;
 +    }
 +    return STATUS_UNSUCCESSFUL;
 +}
 +
 +ULONG
 +NTAPI
 +IKsControl_fnAddRef(
 +    IKsControl * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    return InterlockedIncrement(&This->ref);
 +}
 +
 +ULONG
 +NTAPI
 +IKsControl_fnRelease(
 +    IKsControl * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    InterlockedDecrement(&This->ref);
 +
 +    /* Return new reference count */
 +    return This->ref;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsControl_fnKsProperty(
 +    IKsControl * iface,
 +    IN PKSPROPERTY Property,
 +    IN ULONG PropertyLength,
 +    IN OUT PVOID PropertyData,
 +    IN ULONG DataLength,
 +    OUT ULONG* BytesReturned)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +IKsControl_fnKsMethod(
 +    IKsControl * iface,
 +    IN PKSMETHOD Method,
 +    IN ULONG MethodLength,
 +    IN OUT PVOID MethodData,
 +    IN ULONG DataLength,
 +    OUT ULONG* BytesReturned)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +IKsControl_fnKsEvent(
 +    IKsControl * iface,
 +    IN PKSEVENT Event OPTIONAL,
 +    IN ULONG EventLength,
 +    IN OUT PVOID EventData,
 +    IN ULONG DataLength,
 +    OUT ULONG* BytesReturned)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
 +
 +    if (Event)
 +    {
 +       return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
 +    }
 +    else
 +    {
 +       return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
 +    }
 +
 +}
 +
 +static IKsControlVtbl vt_IKsControl =
 +{
 +    IKsControl_fnQueryInterface,
 +    IKsControl_fnAddRef,
 +    IKsControl_fnRelease,
 +    IKsControl_fnKsProperty,
 +    IKsControl_fnKsMethod,
 +    IKsControl_fnKsEvent
 +};
 +
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnQueryInterface(
 +    IKsFilter * iface,
 +    IN  REFIID refiid,
 +    OUT PVOID* Output)
 +{
 +    NTSTATUS Status;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
 +        IsEqualGUIDAligned(refiid, &IID_IKsFilter))
 +    {
 +        *Output = &This->Header.OuterUnknown;
 +        _InterlockedIncrement(&This->ref);
 +        return STATUS_SUCCESS;
 +    }
 +    else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
 +    {
 +        *Output = &This->lpVtblKsControl;
 +        _InterlockedIncrement(&This->ref);
 +        return STATUS_SUCCESS;
 +    }
 +
 +    if (This->Header.ClientAggregate)
 +    {
 +         /* using client aggregate */
 +         Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
 +
 +         if (NT_SUCCESS(Status))
 +         {
 +             /* client aggregate supports interface */
 +             return Status;
 +         }
 +    }
 +
 +    DPRINT("IKsFilter_fnQueryInterface no interface\n");
 +    return STATUS_NOT_SUPPORTED;
 +}
 +
 +ULONG
 +NTAPI
 +IKsFilter_fnAddRef(
 +    IKsFilter * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    return InterlockedIncrement(&This->ref);
 +}
 +
 +ULONG
 +NTAPI
 +IKsFilter_fnRelease(
 +    IKsFilter * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    InterlockedDecrement(&This->ref);
 +
 +    if (This->ref == 0)
 +    {
 +        FreeItem(This);
 +        return 0;
 +    }
 +    /* Return new reference count */
 +    return This->ref;
 +
 +}
 +
 +PKSFILTER
 +NTAPI
 +IKsFilter_fnGetStruct(
 +    IKsFilter * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    return &This->Filter;
 +}
 +
 +BOOL
 +NTAPI
 +IKsFilter_fnDoAllNecessaryPinsExist(
 +    IKsFilter * iface)
 +{
 +    UNIMPLEMENTED
 +    return FALSE;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnCreateNode(
 +    IKsFilter * iface,
 +    IN PIRP Irp,
 +    IN IKsPin * Pin,
 +    IN PLIST_ENTRY ListEntry)
 +{
 +    UNIMPLEMENTED
 +    return STATUS_NOT_IMPLEMENTED;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnBindProcessPinsToPipeSection(
 +    IKsFilter * iface,
 +    IN struct KSPROCESSPIPESECTION *Section,
 +    IN PVOID Create,
 +    IN PKSPIN KsPin,
 +    OUT IKsPin **Pin,
 +    OUT PKSGATE *OutGate)
 +{
 +    UNIMPLEMENTED
 +    return STATUS_NOT_IMPLEMENTED;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnUnbindProcessPinsFromPipeSection(
 +    IKsFilter * iface,
 +    IN struct KSPROCESSPIPESECTION *Section)
 +{
 +    UNIMPLEMENTED
 +    return STATUS_NOT_IMPLEMENTED;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnAddProcessPin(
 +    IKsFilter * iface,
 +    IN PKSPROCESSPIN ProcessPin)
 +{
 +    NTSTATUS Status;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    /* first acquire processing mutex */
 +    KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 +
 +    /* sanity check */
 +    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
 +
 +    /* allocate new process pin array */
 +    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins,
 +                     (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PKSPROCESSPIN),
 +                     This->Filter.Descriptor->PinDescriptorsCount * sizeof(PKSPROCESSPIN),
 +                     0);
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* store process pin */
 +        This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin;
 +        This->ProcessPinIndex[ProcessPin->Pin->Id].Count++;
 +    }
 +
 +    /* release process mutex */
 +    KeReleaseMutex(&This->ProcessingMutex, FALSE);
 +
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_fnRemoveProcessPin(
 +    IKsFilter * iface,
 +    IN PKSPROCESSPIN ProcessPin)
 +{
 +    ULONG Index;
 +    ULONG Count;
 +    PKSPROCESSPIN * Pins;
 +
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    /* first acquire processing mutex */
 +    KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 +
 +    /* sanity check */
 +    ASSERT(ProcessPin->Pin);
 +    ASSERT(ProcessPin->Pin->Id);
 +
 +    Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
 +    Pins =  This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
 +
 +    /* search for current process pin */
 +    for(Index = 0; Index < Count; Index++)
 +    {
 +        if (Pins[Index] == ProcessPin)
 +        {
 +            RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN));
 +            break;
 +        }
 +
 +    }
 +
 +    /* decrement pin count */
 +    This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
 +
 +    if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
 +    {
 +        /* clear entry object bag will delete it */
 +       This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
 +    }
 +
 +    /* release process mutex */
 +    KeReleaseMutex(&This->ProcessingMutex, FALSE);
 +
 +    /* done */
 +    return STATUS_SUCCESS;
 +}
 +
 +BOOL
 +NTAPI
 +IKsFilter_fnReprepareProcessPipeSection(
 +    IKsFilter * iface,
 +    IN struct KSPROCESSPIPESECTION *PipeSection,
 +    IN PULONG Data)
 +{
 +    UNIMPLEMENTED
 +    return FALSE;
 +}
 +
 +VOID
 +NTAPI
 +IKsFilter_fnDeliverResetState(
 +    IKsFilter * iface,
 +    IN struct KSPROCESSPIPESECTION *PipeSection,
 +    IN KSRESET ResetState)
 +{
 +    UNIMPLEMENTED
 +}
 +
 +BOOL
 +NTAPI
 +IKsFilter_fnIsFrameHolding(
 +    IKsFilter * iface)
 +{
 +    UNIMPLEMENTED
 +    return FALSE;
 +}
 +
 +VOID
 +NTAPI
 +IKsFilter_fnRegisterForCopyCallbacks(
 +    IKsFilter * iface,
 +    IKsQueue *Queue,
 +    BOOL Register)
 +{
 +    UNIMPLEMENTED
 +}
 +
 +PKSPROCESSPIN_INDEXENTRY
 +NTAPI
 +IKsFilter_fnGetProcessDispatch(
 +    IKsFilter * iface)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 +
 +    return This->ProcessPinIndex;
 +}
 +
 +static IKsFilterVtbl vt_IKsFilter =
 +{
 +    IKsFilter_fnQueryInterface,
 +    IKsFilter_fnAddRef,
 +    IKsFilter_fnRelease,
 +    IKsFilter_fnGetStruct,
 +    IKsFilter_fnDoAllNecessaryPinsExist,
 +    IKsFilter_fnCreateNode,
 +    IKsFilter_fnBindProcessPinsToPipeSection,
 +    IKsFilter_fnUnbindProcessPinsFromPipeSection,
 +    IKsFilter_fnAddProcessPin,
 +    IKsFilter_fnRemoveProcessPin,
 +    IKsFilter_fnReprepareProcessPipeSection,
 +    IKsFilter_fnDeliverResetState,
 +    IKsFilter_fnIsFrameHolding,
 +    IKsFilter_fnRegisterForCopyCallbacks,
 +    IKsFilter_fnGetProcessDispatch
 +};
 +
 +NTSTATUS
 +IKsFilter_GetFilterFromIrp(
 +    IN PIRP Irp,
 +    OUT IKsFilter **Filter)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    PKSIOBJECT_HEADER ObjectHeader;
 +    NTSTATUS Status;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* santiy check */
 +    ASSERT(IoStack->FileObject != NULL);
 +
 +    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
 +
 +    /* sanity is important */
 +    ASSERT(ObjectHeader != NULL);
 +    ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
 +    ASSERT(ObjectHeader->Unknown != NULL);
 +
 +    /* get our private interface */
 +    Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* something is wrong here */
 +        DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
 +        Irp->IoStatus.Status = Status;
 +
 +        /* complete and forget irp */
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +        return Status;
 +    }
 +    return Status;
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_DispatchClose(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    IKsFilter * Filter;
 +    IKsFilterImpl * This;
 +    NTSTATUS Status;
 +
 +    /* obtain filter from object header */
 +    Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
 +    if (!NT_SUCCESS(Status))
 +        return Status;
 +
 +    /* get our real implementation */
 +    This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
 +
 +    /* does the driver support notifications */
 +    if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close)
 +    {
 +        /* call driver's filter close function */
 +        Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp);
 +    }
 +
 +    if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
 +    {
 +        /* save the result */
 +        Irp->IoStatus.Status = Status;
 +        /* complete irp */
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +        /* remove our instance from the filter factory */
 +        IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
 +
 +        /* free object header */
 +        KsFreeObjectHeader(This->ObjectHeader);
 +    }
 +    else
 +    {
 +        /* complete and forget */
 +        Irp->IoStatus.Status = Status;
 +        /* complete irp */
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +NTSTATUS
 +KspHandlePropertyInstances(
 +    IN PIO_STATUS_BLOCK IoStatus,
 +    IN PKSIDENTIFIER  Request,
 +    IN OUT PVOID  Data,
 +    IN IKsFilterImpl * This,
 +    IN BOOL Global)
 +{
 +    KSPIN_CINSTANCES * Instances;
 +    KSP_PIN * Pin = (KSP_PIN*)Request;
 +
 +    if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
 +    {
 +        /* no filter / pin descriptor */
 +        IoStatus->Status = STATUS_NOT_IMPLEMENTED;
 +        return STATUS_NOT_IMPLEMENTED;
 +    }
 +
 +    /* ignore custom structs for now */
 +    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
 +    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 +
 +    Instances = (KSPIN_CINSTANCES*)Data;
 +    /* max instance count */
 +    Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
 +    /* current instance count */
 +    Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
 +
 +    IoStatus->Information = sizeof(KSPIN_CINSTANCES);
 +    IoStatus->Status = STATUS_SUCCESS;
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS
 +KspHandleNecessaryPropertyInstances(
 +    IN PIO_STATUS_BLOCK IoStatus,
 +    IN PKSIDENTIFIER  Request,
 +    IN OUT PVOID  Data,
 +    IN IKsFilterImpl * This)
 +{
 +    PULONG Result;
 +    KSP_PIN * Pin = (KSP_PIN*)Request;
 +
 +    if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
 +    {
 +        /* no filter / pin descriptor */
 +        IoStatus->Status = STATUS_NOT_IMPLEMENTED;
 +        return STATUS_NOT_IMPLEMENTED;
 +    }
 +
 +    /* ignore custom structs for now */
 +    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
 +    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 +
 +    Result = (PULONG)Data;
 +    *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
 +
 +    IoStatus->Information = sizeof(ULONG);
 +    IoStatus->Status = STATUS_SUCCESS;
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS
 +KspHandleDataIntersection(
 +    IN PIRP Irp,
 +    IN PIO_STATUS_BLOCK IoStatus,
 +    IN PKSIDENTIFIER Request,
 +    IN OUT PVOID  Data,
 +    IN ULONG DataLength,
 +    IN IKsFilterImpl * This)
 +{
 +    PKSMULTIPLE_ITEM MultipleItem;
 +    PKSDATARANGE DataRange;
 +    NTSTATUS Status = STATUS_NO_MATCH;
 +    ULONG Index, Length;
 +    PIO_STACK_LOCATION IoStack;
 +    KSP_PIN * Pin = (KSP_PIN*)Request;
 +
 +    /* get stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* sanity check */
 +    ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
 +
 +    /* Access parameters */
 +    MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
 +    DataRange = (PKSDATARANGE)(MultipleItem + 1);
 +
 +    /* FIXME make sure its 64 bit aligned */
 +    ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
 +
 +    if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
 +    {
 +        /* no filter / pin descriptor */
 +        IoStatus->Status = STATUS_NOT_IMPLEMENTED;
 +        return STATUS_NOT_IMPLEMENTED;
 +    }
 +
 +    /* ignore custom structs for now */
 +    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
 +    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 +
 +    if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
 +        This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
 +        This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
 +    {
 +        /* no driver supported intersect handler / no provided data ranges */
 +        IoStatus->Status = STATUS_NOT_IMPLEMENTED;
 +        return STATUS_NOT_IMPLEMENTED;
 +    }
 +
 +    for(Index = 0; Index < MultipleItem->Count; Index++)
 +    {
 +        UNICODE_STRING MajorFormat, SubFormat, Specifier;
 +        /* convert the guid to string */
 +        RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat);
 +        RtlStringFromGUID(&DataRange->SubFormat, &SubFormat);
 +        RtlStringFromGUID(&DataRange->Specifier, &Specifier);
 +
 +        DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer,
 +               DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength);
 +
 +        /* FIXME implement KsPinDataIntersectionEx */
 +        /* Call miniport's properitary handler */
 +        Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter,
 +                                                                                      Irp,
 +                                                                                      Pin,
 +                                                                                      DataRange,
 +                                                                                      This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */
 +                                                                                      DataLength,
 +                                                                                      Data,
 +                                                                                      &Length);
 +        DPRINT("KspHandleDataIntersection Status %lx\n", Status);
 +
 +        if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
 +        {
 +            ASSERT(Length);
 +            IoStatus->Information = Length;
 +            break;
 +        }
 +
 +        DataRange =  UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
 +        /* FIXME make sure its 64 bit aligned */
 +        ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
 +    }
 +    IoStatus->Status = Status;
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +FilterTopologyPropertyHandler(
 +    IN PIRP Irp,
 +    IN PKSIDENTIFIER  Request,
 +    IN OUT PVOID  Data)
 +{
 +    IKsFilterImpl * This;
 +
 +    /* get filter implementation */
 +    This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
 +
 +    /* sanity check */
 +    ASSERT(This);
 +
 +    return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology);
 +
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +FilterPinPropertyHandler(
 +    IN PIRP Irp,
 +    IN PKSIDENTIFIER  Request,
 +    IN OUT PVOID  Data)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    IKsFilterImpl * This;
 +    NTSTATUS Status = STATUS_UNSUCCESSFUL;
 +
 +    /* get filter implementation */
 +    This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
 +
 +    /* sanity check */
 +    ASSERT(This);
 +
 +    /* get current stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    switch(Request->Id)
 +    {
 +        case KSPROPERTY_PIN_CTYPES:
 +        case KSPROPERTY_PIN_DATAFLOW:
 +        case KSPROPERTY_PIN_DATARANGES:
 +        case KSPROPERTY_PIN_INTERFACES:
 +        case KSPROPERTY_PIN_MEDIUMS:
 +        case KSPROPERTY_PIN_COMMUNICATION:
 +        case KSPROPERTY_PIN_CATEGORY:
 +        case KSPROPERTY_PIN_NAME:
 +        case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
 +            Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize);
 +            break;
 +        case KSPROPERTY_PIN_GLOBALCINSTANCES:
 +            Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
 +            break;
 +        case KSPROPERTY_PIN_CINSTANCES:
 +            Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
 +            break;
 +        case KSPROPERTY_PIN_NECESSARYINSTANCES:
 +            Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
 +            break;
 +
 +        case KSPROPERTY_PIN_DATAINTERSECTION:
 +            Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
 +            break;
 +        default:
 +            UNIMPLEMENTED
 +            Status = STATUS_NOT_FOUND;
 +    }
 +    //DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
 +
 +
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_DispatchDeviceIoControl(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    IKsFilter * Filter;
 +    IKsFilterImpl * This;
 +    NTSTATUS Status;
 +    PKSFILTER FilterInstance;
 +    UNICODE_STRING GuidString;
 +    PKSPROPERTY Property;
 +    ULONG SetCount = 0;
 +
 +    /* obtain filter from object header */
 +    Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
 +    if (!NT_SUCCESS(Status))
 +        return Status;
 +
 +    /* get our real implementation */
 +    This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
 +
 +    /* current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* get property from input buffer */
 +    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
 +
 +    /* get filter instance */
 +    FilterInstance = Filter->lpVtbl->GetStruct(Filter);
 +
 +    /* sanity check */
 +    ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
 +    ASSERT(FilterInstance);
 +    ASSERT(FilterInstance->Descriptor);
 +    ASSERT(FilterInstance->Descriptor->AutomationTable);
 +
 +    /* acquire control mutex */
 +    KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
 +
 +    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
 +    {
 +        const KSMETHOD_SET *MethodSet = NULL;
 +        ULONG MethodItemSize = 0;
 +
 +        /* check if the driver supports method sets */
 +        if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
 +        {
 +            SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
 +            MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
 +            MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
 +        }
 +
 +        /* call method set handler */
 +        Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
 +    }
 +    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
 +    {
 +        const KSPROPERTY_SET *PropertySet = NULL;
 +        ULONG PropertyItemSize = 0;
 +
 +        /* check if the driver supports method sets */
 +        if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
 +        {
 +            SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
 +            PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
 +            PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
 +        }
 +
 +        /* needed for our property handlers */
 +        KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
 +
 +        /* call property handler */
 +        Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
 +    }
 +    else
 +    {
 +        /* sanity check */
 +        ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
 +               IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
 +
 +        if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
 +        {
 +            /* call enable event handlers */
 +            Status = KspEnableEvent(Irp,
 +                                    FilterInstance->Descriptor->AutomationTable->EventSetsCount,
 +                                    (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
 +                                    &This->Header.EventList,
 +                                    KSEVENTS_SPINLOCK,
 +                                    (PVOID)&This->Header.EventListLock,
 +                                    NULL,
 +                                    FilterInstance->Descriptor->AutomationTable->EventItemSize);
 +        }
 +        else
 +        {
 +            /* disable event handler */
 +            Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
 +        }
 +    }
 +
 +    RtlStringFromGUID(&Property->Set, &GuidString);
 +    DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
 +    RtlFreeUnicodeString(&GuidString);
 +
 +    /* release filter */
 +    Filter->lpVtbl->Release(Filter);
 +
 +    /* release control mutex */
 +    KeReleaseMutex(This->Header.ControlMutex, FALSE);
 +
 +    if (Status != STATUS_PENDING)
 +    {
 +        Irp->IoStatus.Status = Status;
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +static KSDISPATCH_TABLE DispatchTable =
 +{
 +    IKsFilter_DispatchDeviceIoControl,
 +    KsDispatchInvalidDeviceRequest,
 +    KsDispatchInvalidDeviceRequest,
 +    KsDispatchInvalidDeviceRequest,
 +    IKsFilter_DispatchClose,
 +    KsDispatchQuerySecurity,
 +    KsDispatchSetSecurity,
 +    KsDispatchFastIoDeviceControlFailure,
 +    KsDispatchFastReadFailure,
 +    KsDispatchFastReadFailure,
 +};
 +
 +
 +NTSTATUS
 +IKsFilter_CreateDescriptors(
 +    IKsFilterImpl * This,
 +    KSFILTER_DESCRIPTOR* FilterDescriptor)
 +{
 +    ULONG Index = 0;
 +    NTSTATUS Status;
 +
 +    /* initialize pin descriptors */
 +    This->FirstPin = NULL;
 +    This->PinInstanceCount = NULL;
 +    This->ProcessPinIndex = NULL;
 +
 +    /* initialize topology descriptor */
 +    This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
 +    This->Topology.Categories = FilterDescriptor->Categories;
 +    This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
 +    This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
 +    This->Topology.TopologyConnections = FilterDescriptor->Connections;
 +
 +    /* are there any templates */
 +    if (FilterDescriptor->PinDescriptorsCount)
 +    {
 +        /* sanity check */
 +        ASSERT(FilterDescriptor->PinDescriptors);
 +
 +        /* FIXME handle variable sized pin descriptors */
 +        ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
 +
 +        /* store pin descriptors ex */
 +        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
 +                         FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
 +            return Status;
 +        }
 +
 +        /* store pin instance count */
 +        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
 +                         sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
 +            return Status;
 +        }
 +
 +        /* store instantiated pin arrays */
 +        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
 +                         sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
 +            return Status;
 +        }
 +
 +        /* add new pin factory */
 +        RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
 +
 +        /* allocate process pin index */
 +        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
 +                         sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
 +            return Status;
 +        }
 +
 +    }
 +
 +
 +    if (FilterDescriptor->ConnectionsCount)
 +    {
 +        /* modify connections array */
 +        Status = _KsEdit(This->Filter.Bag,
 +                        (PVOID*)&This->Filter.Descriptor->Connections,
 +                         FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
 +                         FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
 +                         0);
 +
 +       This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
 +       This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
 +    }
 +
 +    if (FilterDescriptor->NodeDescriptorsCount)
 +    {
 +        /* sanity check */
 +        ASSERT(FilterDescriptor->NodeDescriptors);
 +
 +        /* FIXME handle variable sized node descriptors */
 +        ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
 +
 +        This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
 +        /* allocate topology node types array */
 +        if (!This->Topology.TopologyNodes)
 +        {
 +            DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
 +            return STATUS_INSUFFICIENT_RESOURCES;
 +        }
 +
 +        This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
 +        /* allocate topology names array */
 +        if (!This->Topology.TopologyNodesNames)
 +        {
 +            FreeItem((PVOID)This->Topology.TopologyNodes);
 +            DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
 +            return STATUS_INSUFFICIENT_RESOURCES;
 +        }
 +
 +        DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
 +        for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
 +        {
 +            DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
 +
 +            /* copy topology type */
 +            if (FilterDescriptor->NodeDescriptors[Index].Type)
 +                RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
 +
 +            /* copy topology name */
 +            if (FilterDescriptor->NodeDescriptors[Index].Name)
 +                RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
 +        }
 +    }
 +    /* done! */
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS
 +IKsFilter_CopyFilterDescriptor(
 +    IKsFilterImpl * This,
 +    const KSFILTER_DESCRIPTOR* FilterDescriptor)
 +{
 +    NTSTATUS Status;
 +    KSAUTOMATION_TABLE AutomationTable;
 +
 +    This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
 +    if (!This->Filter.Descriptor)
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +
 +    Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        FreeItem((PVOID)This->Filter.Descriptor);
 +        This->Filter.Descriptor = NULL;
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* copy filter descriptor fields */
 +    RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
 +
 +    /* zero automation table */
 +    RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
 +
 +    /* setup filter property sets */
 +    AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
 +    AutomationTable.PropertySetsCount = 2;
 +    AutomationTable.PropertySets = FilterPropertySet;
 +
 +    /* merge filter automation table */
 +    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
 +
 +    return Status;
 +}
 +
 +
 +VOID
 +IKsFilter_AddPin(
 +    PKSFILTER Filter,
 +    PKSPIN Pin)
 +{
 +    PKSPIN NextPin, CurPin;
 +    PKSBASIC_HEADER BasicHeader;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    /* sanity check */
 +    ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
 +
 +    if (This->FirstPin[Pin->Id] == NULL)
 +    {
 +        /* welcome first pin */
 +        This->FirstPin[Pin->Id] = Pin;
 +        This->PinInstanceCount[Pin->Id]++;
 +        return;
 +    }
 +
 +    /* get first pin */
 +    CurPin = This->FirstPin[Pin->Id];
 +
 +    do
 +    {
 +        /* get next instantiated pin */
 +        NextPin = KsPinGetNextSiblingPin(CurPin);
 +        if (!NextPin)
 +            break;
 +
 +        NextPin = CurPin;
 +
 +    }while(NextPin != NULL);
 +
 +    /* get basic header */
 +    BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
 +
 +    /* store pin */
 +    BasicHeader->Next.Pin = Pin;
 +}
 +
 +VOID
 +IKsFilter_RemovePin(
 +    PKSFILTER Filter,
 +    PKSPIN Pin)
 +{
 +    PKSPIN NextPin, CurPin, LastPin;
 +    PKSBASIC_HEADER BasicHeader;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    /* sanity check */
 +    ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
 +
 +    /* get first pin */
 +    CurPin = This->FirstPin[Pin->Id];
 +
 +    LastPin = NULL;
 +    do
 +    {
 +        /* get next instantiated pin */
 +        NextPin = KsPinGetNextSiblingPin(CurPin);
 +
 +        if (CurPin == Pin)
 +        {
 +            if (LastPin)
 +            {
 +                /* get basic header of last pin */
 +                BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
 +
 +                BasicHeader->Next.Pin = NextPin;
 +            }
 +            else
 +            {
 +                /* erase last pin */
 +                This->FirstPin[Pin->Id] = NextPin;
 +            }
 +            /* decrement pin instance count */
 +            This->PinInstanceCount[Pin->Id]--;
 +            return;
 +        }
 +
 +        if (!NextPin)
 +            break;
 +
 +        LastPin = CurPin;
 +        NextPin = CurPin;
 +
 +    }while(NextPin != NULL);
 +
 +    /* pin not found */
 +    ASSERT(0);
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_DispatchCreatePin(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    IKsFilterImpl * This;
 +    PKSOBJECT_CREATE_ITEM CreateItem;
 +    PKSPIN_CONNECT Connect;
 +    NTSTATUS Status;
 +
 +    DPRINT("IKsFilter_DispatchCreatePin\n");
 +
 +    /* get the create item */
 +    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 +
 +    /* get the filter object */
 +    This = (IKsFilterImpl*)CreateItem->Context;
 +
 +    /* sanity check */
 +    ASSERT(This->Header.Type == KsObjectTypeFilter);
 +
 +    /* acquire control mutex */
 +    KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
 +
 +    /* now validate the connect request */
 +    Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
 +
 +    DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* sanity check */
 +        ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
 +
 +        DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, 
 +               This->PinInstanceCount[Connect->PinId],
 +               This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
 +
 +        if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
 +        {
 +            /* create the pin */
 +            Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
 +
 +            DPRINT("IKsFilter_DispatchCreatePin  KspCreatePin %lx\n", Status);
 +        }
 +        else
 +        {
 +            /* maximum instance count reached, bye-bye */
 +            Status = STATUS_UNSUCCESSFUL;
 +            DPRINT("IKsFilter_DispatchCreatePin  MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
 +        }
 +    }
 +
 +    /* release control mutex */
 +    KeReleaseMutex(This->Header.ControlMutex, FALSE);
 +
 +    if (Status != STATUS_PENDING)
 +    {
 +        /* complete request */
 +        Irp->IoStatus.Status = Status;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +    }
 +
 +    /* done */
 +    DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
 +    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +IKsFilter_DispatchCreateNode(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    UNIMPLEMENTED
 +    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-     if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +    return STATUS_UNSUCCESSFUL;
 +}
 +
 +
 +VOID
 +IKsFilter_AttachFilterToFilterFactory(
 +    IKsFilterImpl * This,
 +    PKSFILTERFACTORY FilterFactory)
 +{
 +    PKSBASIC_HEADER BasicHeader;
 +    PKSFILTER Filter;
 +
 +
 +    /* get filter factory basic header */
 +    BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
 +
 +    /* sanity check */
 +    ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
 +
 +    if (BasicHeader->FirstChild.FilterFactory == NULL)
 +    {
 +        /* welcome first instantiated filter */
 +        BasicHeader->FirstChild.Filter = &This->Filter;
 +        return;
 +    }
 +
 +    /* set to first entry */
 +    Filter = BasicHeader->FirstChild.Filter;
 +
 +    do
 +    {
 +        /* get basic header */
 +        BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
 +        /* sanity check */
 +        ASSERT(BasicHeader->Type == KsObjectTypeFilter);
 +
 +        if (BasicHeader->Next.Filter)
 +        {
 +            /* iterate to next filter factory */
 +            Filter = BasicHeader->Next.Filter;
 +        }
 +        else
 +        {
 +            /* found last entry */
 +            break;
 +        }
 +    }while(TRUE);
 +
 +    /* attach filter factory */
 +    BasicHeader->Next.Filter = &This->Filter;
 +}
 +
 +VOID
 +IKsFilter_RemoveFilterFromFilterFactory(
 +    IKsFilterImpl * This,
 +    PKSFILTERFACTORY FilterFactory)
 +{
 +    PKSBASIC_HEADER BasicHeader;
 +    PKSFILTER Filter, LastFilter;
 +
 +    /* get filter factory basic header */
 +    BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
 +
 +    /* sanity check */
 +    ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
 +    ASSERT(BasicHeader->FirstChild.Filter != NULL);
 +
 +
 +    /* set to first entry */
 +    Filter = BasicHeader->FirstChild.Filter;
 +    LastFilter = NULL;
 +
 +    do
 +    {
 +         if (Filter == &This->Filter)
 +         {
 +             if (LastFilter)
 +             {
 +                 /* get basic header */
 +                 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
 +                 /* remove filter instance */
 +                 BasicHeader->Next.Filter = This->Header.Next.Filter;
 +                 break;
 +             }
 +             else
 +             {
 +                 /* remove filter instance */
 +                 BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
 +                 break;
 +             }
 +         }
 +
 +        /* get basic header */
 +        BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
 +        /* sanity check */
 +        ASSERT(BasicHeader->Type == KsObjectTypeFilter);
 +
 +        LastFilter = Filter;
 +        if (BasicHeader->Next.Filter)
 +        {
 +            /* iterate to next filter factory */
 +            Filter = BasicHeader->Next.Filter;
 +        }
 +        else
 +        {
 +            /* filter is not in list */
 +            ASSERT(0);
 +            break;
 +        }
 +    }while(TRUE);
 +}
 +
++VOID
++NTAPI
++IKsFilter_FilterCentricWorker(
++    IN PVOID Ctx)
++{
++    IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
++
++    /* sanity check */
++    ASSERT(Object);
++
++    /* perform work */
++    Object->lpVtbl->ProcessingObjectWork(Object);
++}
++
 +NTSTATUS
 +NTAPI
 +KspCreateFilter(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp,
 +    IN IKsFilterFactory *iface)
 +{
 +    IKsFilterImpl * This;
 +    IKsDevice *KsDevice;
 +    PKSFILTERFACTORY Factory;
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_EXTENSION DeviceExtension;
 +    NTSTATUS Status;
 +    PKSOBJECT_CREATE_ITEM CreateItem;
 +
 +    /* get device extension */
 +    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +
 +    /* get the filter factory */
 +    Factory = iface->lpVtbl->GetStruct(iface);
 +
-         DPRINT("KspCreateFilter OutOfMemory\n");
++    if (!Factory || !Factory->FilterDescriptor)
 +    {
 +        /* Sorry it just will not work */
 +        return STATUS_UNSUCCESSFUL;
 +    }
 +
++    if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
++    {
++        if (Irp->RequestorMode == UserMode)
++        {
++            /* filter not accessible from user mode */
++            DPRINT1("Access denied\n");
++            return STATUS_UNSUCCESSFUL;
++        }
++    }
++
 +    /* allocate filter instance */
 +    This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
 +    if (!This)
 +    {
-         DPRINT("KspCreateFilter OutOfMemory\n");
++        DPRINT1("KspCreateFilter OutOfMemory\n");
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* initialize object bag */
 +    This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
 +    if (!This->Filter.Bag)
 +    {
 +        /* no memory */
 +        FreeItem(This);
-         DPRINT("KspCreateFilter OutOfMemory\n");
++        DPRINT1("KspCreateFilter OutOfMemory\n");
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +    KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
 +    KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
 +
 +    /* copy filter descriptor */
 +    Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* not enough memory */
 +        FreeItem(This->Filter.Bag);
 +        FreeItem(This);
 +        DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* allocate create items */
 +    CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
 +    if (!CreateItem)
 +    {
 +        /* no memory */
 +        FreeItem(This->Filter.Bag);
 +        FreeItem(This);
-     DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags);
++        DPRINT1("KspCreateFilter OutOfMemory\n");
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
-         DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
 +    /* initialize pin create item */
 +    CreateItem[0].Create = IKsFilter_DispatchCreatePin;
 +    CreateItem[0].Context = (PVOID)This;
 +    CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
 +    RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
 +    /* initialize node create item */
 +    CreateItem[1].Create = IKsFilter_DispatchCreateNode;
 +    CreateItem[1].Context = (PVOID)This;
 +    CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
 +    RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
 +
 +
 +    /* initialize filter instance */
 +    This->ref = 1;
 +    This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
 +    This->lpVtblKsControl = &vt_IKsControl;
++    This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
 +
 +    This->Factory = Factory;
 +    This->FilterFactory = iface;
 +    This->FileObject = IoStack->FileObject;
 +    KeInitializeMutex(&This->ProcessingMutex, 0);
++
 +    /* initialize basic header */
 +    This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
 +    This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
 +    This->Header.Type = KsObjectTypeFilter;
 +    This->Header.ControlMutex = &This->ControlMutex;
 +    KeInitializeMutex(This->Header.ControlMutex, 0);
 +    InitializeListHead(&This->Header.EventList);
 +    KeInitializeSpinLock(&This->Header.EventListLock);
 +
++    /* initialize and gate */
++    KsGateInitializeAnd(&This->Gate, NULL);
++
++    /* FIXME initialize and gate based on pin flags */
++
++    /* initialize work item */
++    ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
++
++    /* allocate counted work item */
++    Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
++    if (!NT_SUCCESS(Status))
++    {
++        /* what can go wrong, goes wrong */
++        DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
++        FreeItem(This);
++        FreeItem(CreateItem);
++        return Status;
++    }
++
 +    /* allocate the stream descriptors */
 +    Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* what can go wrong, goes wrong */
++        DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
++        KsUnregisterWorker(This->Worker);
 +        FreeItem(This);
 +        FreeItem(CreateItem);
-     DPRINT("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
 +        return Status;
 +    }
 +
++
++
 +    /* does the filter have a filter dispatch */
 +    if (Factory->FilterDescriptor->Dispatch)
 +    {
 +        /* does it have a create routine */
 +        if (Factory->FilterDescriptor->Dispatch->Create)
 +        {
 +            /* now let driver initialize the filter instance */
 +
 +            ASSERT(This->Header.KsDevice);
 +            ASSERT(This->Header.KsDevice->Started);
 +            Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
 +
 +            if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
 +            {
 +                /* driver failed to initialize */
 +                DPRINT1("Driver: Status %x\n", Status);
 +
 +                /* free filter instance */
++                KsUnregisterWorker(This->Worker);
 +                FreeItem(This);
 +                FreeItem(CreateItem);
 +                return Status;
 +            }
 +        }
 +    }
 +
 +    /* now allocate the object header */
 +    Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed to allocate object header */
 +        DPRINT1("Failed to allocate object header %x\n", Status);
 +
 +        return Status;
 +    }
 +
 +    /* initialize object header extra fields */
 +    This->ObjectHeader->Type = KsObjectTypeFilter;
 +    This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
 +    This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
 +
 +    /* attach filter to filter factory */
 +    IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
 +
 +    /* completed initialization */
-     @unimplemented
++    DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsFilterAcquireProcessingMutex(
 +    IN PKSFILTER Filter)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsFilterReleaseProcessingMutex(
 +    IN PKSFILTER Filter)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    KeReleaseMutex(&This->ProcessingMutex, FALSE);
 +}
 +
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsFilterAddTopologyConnections (
 +    IN PKSFILTER Filter,
 +    IN ULONG NewConnectionsCount,
 +    IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
 +{
 +    ULONG Count;
 +    NTSTATUS Status;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    DPRINT("KsFilterAddTopologyConnections\n");
 +
 +    ASSERT(This->Filter.Descriptor);
 +    Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
 +
 +
 +    /* modify connections array */
 +    Status = _KsEdit(This->Filter.Bag,
 +                    (PVOID*)&This->Filter.Descriptor->Connections,
 +                     Count * sizeof(KSTOPOLOGY_CONNECTION),
 +                     This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
 +                     0);
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
 +        return Status;
 +    }
 +
 +    /* FIXME verify connections */
 +
 +    /* copy new connections */
 +    RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
 +                  NewTopologyConnections,
 +                  NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
 +
 +    /* update topology */
 +    This->Topology.TopologyConnectionsCount += NewConnectionsCount;
 +    ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
 +    This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
 +
 +    return Status;
 +}
 +
 +/*
-     UNIMPLEMENTED
++    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsFilterAttemptProcessing(
 +    IN PKSFILTER Filter,
 +    IN BOOLEAN Asynchronous)
 +{
-     UNIMPLEMENTED
-     return NULL;
++    PKSGATE Gate;
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
++
++    /* get gate */
++    Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
++
++    if (!KsGateCaptureThreshold(Gate))
++    {
++        /* filter control gate is closed */
++        return;
++    }
++DPRINT1("processing\n");
++    /* try initiate processing */
++    This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
 +}
 +
 +/*
 +    @unimplemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsFilterCreateNode (
 +    IN PKSFILTER Filter,
 +    IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
 +    OUT PULONG NodeID)
 +{
 +    UNIMPLEMENTED
 +    return STATUS_NOT_IMPLEMENTED;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsFilterCreatePinFactory (
 +    IN PKSFILTER Filter,
 +    IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
 +    OUT PULONG PinID)
 +{
 +    ULONG Count;
 +    NTSTATUS Status;
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    DPRINT("KsFilterCreatePinFactory\n");
 +
 +    /* calculate new count */
 +    Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
 +
 +    /* sanity check */
 +    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
 +
 +    /* modify pin descriptors ex array */
 +    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
 +        return Status;
 +    }
 +
 +    /* modify pin instance count array */
 +    Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
 +        return Status;
 +    }
 +
 +    /* modify first pin array */
 +    Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->Filter.Descriptor->PinDescriptorsCount, 0);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
 +        return Status;
 +    }
 +
 +    /* add new pin factory */
 +    RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
 +
 +    /* allocate process pin index */
 +    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
 +                     sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
 +        return Status;
 +    }
 +
 +    /* store new pin id */
 +    *PinID = This->Filter.Descriptor->PinDescriptorsCount;
 +
 +    /* increment pin descriptor count */
 +    ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
 +
 +
 +    DPRINT("KsFilterCreatePinFactory done\n");
 +    return STATUS_SUCCESS;
 +
 +}
 +
 +/*
 +    @unimplemented
 +*/
 +KSDDKAPI
 +PKSGATE
 +NTAPI
 +KsFilterGetAndGate(
 +    IN PKSFILTER Filter)
 +{
++    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
++
++    /* return and-gate */
++    return &This->Gate;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +ULONG
 +NTAPI
 +KsFilterGetChildPinCount(
 +    IN PKSFILTER Filter,
 +    IN ULONG PinId)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
 +    {
 +        /* index is out of bounds */
 +        return 0;
 +    }
 +    /* return pin instance count */
 +    return This->PinInstanceCount[PinId];
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +PKSPIN
 +NTAPI
 +KsFilterGetFirstChildPin(
 +    IN PKSFILTER Filter,
 +    IN ULONG PinId)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
 +    {
 +        /* index is out of bounds */
 +        return NULL;
 +    }
 +
 +    /* return first pin index */
 +    return This->FirstPin[PinId];
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsFilterRegisterPowerCallbacks(
 +    IN PKSFILTER Filter,
 +    IN PFNKSFILTERPOWER Sleep OPTIONAL,
 +    IN PFNKSFILTERPOWER Wake OPTIONAL)
 +{
 +    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 +
 +    This->Sleep = Sleep;
 +    This->Wake = Wake;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +PKSFILTER
 +NTAPI
 +KsGetFilterFromIrp(
 +    IN PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    PKSIOBJECT_HEADER ObjectHeader;
 +
 +    DPRINT("KsGetFilterFromIrp\n");
 +
 +    /* get current irp stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* sanity check */
 +    ASSERT(IoStack->FileObject);
 +
 +    /* get object header */
 +    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
 +
 +    if (ObjectHeader->Type == KsObjectTypeFilter)
 +    {
 +        /* irp is targeted at the filter */
 +        return (PKSFILTER)ObjectHeader->ObjectType;
 +    }
 +    else if (ObjectHeader->Type == KsObjectTypePin)
 +    {
 +        /* irp is for a pin */
 +        return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
 +    }
 +    else
 +    {
 +        /* irp is unappropiate to retrieve a filter */
 +        return NULL;
 +    }
 +}
index fb36d6d,0000000..2fa100a
mode 100644,000000..100644
--- /dev/null
@@@ -1,2132 -1,0 +1,2132 @@@
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Kernel Streaming
 + * FILE:            drivers/ksfilter/ks/factory.c
 + * PURPOSE:         KS Allocator functions
 + * PROGRAMMER:      Johannes Anderwald
 + */
 +
 +
 +#include "priv.h"
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDispatchQuerySecurity(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    PKSOBJECT_CREATE_ITEM CreateItem;
 +    PIO_STACK_LOCATION IoStack;
 +    NTSTATUS Status;
 +    ULONG Length;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* get create item */
 +    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 +
 +    if (!CreateItem || !CreateItem->SecurityDescriptor)
 +    {
 +        /* no create item */
 +        Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +        return STATUS_NO_SECURITY_ON_OBJECT;
 +    }
 +
 +
 +    /* get input length */
 +    Length = IoStack->Parameters.QuerySecurity.Length;
 +
 +    /* clone the security descriptor */
 +    Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)Irp->UserBuffer, &Length, &CreateItem->SecurityDescriptor);
 +
 +    DPRINT("SeQuerySecurityDescriptorInfo Status %x\n", Status);
 +    /* store result */
 +    Irp->IoStatus.Status = Status;
 +    Irp->IoStatus.Information = Length;
 +
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDispatchSetSecurity(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    PKSOBJECT_CREATE_ITEM CreateItem;
 +    PIO_STACK_LOCATION IoStack;
 +    PGENERIC_MAPPING Mapping;
 +    PSECURITY_DESCRIPTOR Descriptor;
 +    NTSTATUS Status;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* get create item */
 +    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 +
 +    if (!CreateItem || !CreateItem->SecurityDescriptor)
 +    {
 +        /* no create item */
 +        Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +        return STATUS_NO_SECURITY_ON_OBJECT;
 +    }
 +
 +    /* backup old descriptor */
 +    Descriptor = CreateItem->SecurityDescriptor;
 +
 +    /* get generic mapping */
 +    Mapping = IoGetFileObjectGenericMapping();
 +
 +    /* change security descriptor */
 +    Status = SeSetSecurityDescriptorInfo(NULL, /*FIXME */
 +                                         &IoStack->Parameters.SetSecurity.SecurityInformation,
 +                                         IoStack->Parameters.SetSecurity.SecurityDescriptor,
 +                                         &CreateItem->SecurityDescriptor,
 +                                         NonPagedPool,
 +                                         Mapping);
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* free old descriptor */
 +        FreeItem(Descriptor);
 +
 +       /* mark create item as changed */
 +       CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED;
 +    }
 +
 +    /* store result */
 +    Irp->IoStatus.Status = Status;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    return Status;
 +}
 +
 +/*
 +    @unimplemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDispatchSpecificMethod(
 +    IN  PIRP Irp,
 +    IN  PFNKSHANDLER Handler)
 +{
 +    UNIMPLEMENTED;
 +    return STATUS_UNSUCCESSFUL;
 +}
 +
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsReadFile(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  PKEVENT Event OPTIONAL,
 +    IN  PVOID PortContext OPTIONAL,
 +    OUT PIO_STATUS_BLOCK IoStatusBlock,
 +    OUT PVOID Buffer,
 +    IN  ULONG Length,
 +    IN  ULONG Key OPTIONAL,
 +    IN  KPROCESSOR_MODE RequestorMode)
 +{
 +    PDEVICE_OBJECT DeviceObject;
 +    PIRP Irp;
 +    NTSTATUS Status;
 +    BOOLEAN Result;
 +    KEVENT LocalEvent;
 +
 +    if (Event)
 +    {
 +        /* make sure event is reset */
 +        KeClearEvent(Event);
 +    }
 +
 +    if (RequestorMode == UserMode)
 +    {
 +        /* probe the user buffer */
 +        _SEH2_TRY
 +        {
 +            ProbeForWrite(Buffer, Length, sizeof(UCHAR));
 +            Status = STATUS_SUCCESS;
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            /* Exception, get the error code */
 +            Status = _SEH2_GetExceptionCode();
 +        }
 +        _SEH2_END;
 +
 +         if (!NT_SUCCESS(Status))
 +         {
 +             DPRINT1("Invalid user buffer provided\n");
 +             return Status;
 +         }
 +    }
 +
 +    /* get corresponding device object */
 +    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 +
 +    /* fast-io read is only available for kernel mode clients */
 +    if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
 +        DeviceObject->DriverObject->FastIoDispatch->FastIoRead)
 +    {
 +        /* call fast io write */
 +        Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
 +
 +        if (Result && NT_SUCCESS(IoStatusBlock->Status))
 +        {
 +            /* request was handeled and succeeded */
 +            return STATUS_SUCCESS;
 +        }
 +    }
 +
 +    /* do the slow way */
 +    if (!Event)
 +    {
 +        /* initialize temp event */
 +        KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
 +        Event = &LocalEvent;
 +    }
 +
 +    /* build the irp packet */
 +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
 +    if (!Irp)
 +    {
 +        /* not enough resources */
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* send the packet */
 +    Status = IoCallDriver(DeviceObject, Irp);
 +
 +    if (Status == STATUS_PENDING)
 +    {
 +        /* operation is pending, is sync file object */
 +        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
 +        {
 +            /* it is so wait */
 +            KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
 +            Status = IoStatusBlock->Status;
 +        }
 +    }
 +    /* return result */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsWriteFile(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  PKEVENT Event OPTIONAL,
 +    IN  PVOID PortContext OPTIONAL,
 +    OUT PIO_STATUS_BLOCK IoStatusBlock,
 +    IN  PVOID Buffer,
 +    IN  ULONG Length,
 +    IN  ULONG Key OPTIONAL,
 +    IN  KPROCESSOR_MODE RequestorMode)
 +{
 +    PDEVICE_OBJECT DeviceObject;
 +    PIRP Irp;
 +    NTSTATUS Status;
 +    BOOLEAN Result;
 +    KEVENT LocalEvent;
 +
 +    if (Event)
 +    {
 +        /* make sure event is reset */
 +        KeClearEvent(Event);
 +    }
 +
 +    if (RequestorMode == UserMode)
 +    {
 +        /* probe the user buffer */
 +        _SEH2_TRY
 +        {
 +            ProbeForRead(Buffer, Length, sizeof(UCHAR));
 +            Status = STATUS_SUCCESS;
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            /* Exception, get the error code */
 +            Status = _SEH2_GetExceptionCode();
 +        }
 +        _SEH2_END;
 +
 +         if (!NT_SUCCESS(Status))
 +         {
 +             DPRINT1("Invalid user buffer provided\n");
 +             return Status;
 +         }
 +    }
 +
 +    /* get corresponding device object */
 +    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 +
 +    /* fast-io write is only available for kernel mode clients */
 +    if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
 +        DeviceObject->DriverObject->FastIoDispatch->FastIoWrite)
 +    {
 +        /* call fast io write */
 +        Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
 +
 +        if (Result && NT_SUCCESS(IoStatusBlock->Status))
 +        {
 +            /* request was handeled and succeeded */
 +            return STATUS_SUCCESS;
 +        }
 +    }
 +
 +    /* do the slow way */
 +    if (!Event)
 +    {
 +        /* initialize temp event */
 +        KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
 +        Event = &LocalEvent;
 +    }
 +
 +    /* build the irp packet */
 +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
 +    if (!Irp)
 +    {
 +        /* not enough resources */
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* send the packet */
 +    Status = IoCallDriver(DeviceObject, Irp);
 +
 +    if (Status == STATUS_PENDING)
 +    {
 +        /* operation is pending, is sync file object */
 +        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
 +        {
 +            /* it is so wait */
 +            KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
 +            Status = IoStatusBlock->Status;
 +        }
 +    }
 +    /* return result */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsQueryInformationFile(
 +    IN  PFILE_OBJECT FileObject,
 +    OUT PVOID FileInformation,
 +    IN  ULONG Length,
 +    IN  FILE_INFORMATION_CLASS FileInformationClass)
 +{
 +    PDEVICE_OBJECT DeviceObject;
 +    PFAST_IO_DISPATCH FastIoDispatch;
 +    PIRP Irp;
 +    PIO_STACK_LOCATION IoStack;
 +    IO_STATUS_BLOCK IoStatus;
 +    KEVENT Event;
 +    LARGE_INTEGER Offset;
 +    IO_STATUS_BLOCK StatusBlock;
 +    NTSTATUS Status;
 +
 +    /* get related file object */
 +    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 +
 +    /* get fast i/o table */
 +    FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
 +
 +    /* is there a fast table */
 +    if (FastIoDispatch)
 +    {
 +        /* check the class */
 +        if (FileInformationClass == FileBasicInformation)
 +        {
 +            /* use FastIoQueryBasicInfo routine */
 +            if (FastIoDispatch->FastIoQueryBasicInfo)
 +            {
 +                return FastIoDispatch->FastIoQueryBasicInfo(FileObject, TRUE, (PFILE_BASIC_INFORMATION)FileInformation, &IoStatus, DeviceObject);
 +            }
 +        }
 +        else if (FileInformationClass == FileStandardInformation)
 +        {
 +            /* use FastIoQueryBasicInfo routine */
 +            if (FastIoDispatch->FastIoQueryBasicInfo)
 +            {
 +                return FastIoDispatch->FastIoQueryStandardInfo(FileObject, TRUE, (PFILE_STANDARD_INFORMATION)FileInformation, &IoStatus, DeviceObject);
 +            }
 +        }
 +    }
 +    /* clear event */
 +    KeClearEvent(&FileObject->Event);
 +
 +    /* initialize event */
 +    KeInitializeEvent(&Event, NotificationEvent, FALSE);
 +
 +    /* set offset to zero */
 +    Offset.QuadPart = 0L;
 +
 +    /* build the request */
 +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &StatusBlock);
 +
 +    if (!Irp)
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +
 +    /* get next stack location */
 +    IoStack = IoGetNextIrpStackLocation(Irp);
 +
 +    /* setup parameters */
 +    IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
 +    IoStack->Parameters.QueryFile.Length = Length;
 +    Irp->AssociatedIrp.SystemBuffer = FileInformation;
 +
 +
 +    /* call the driver */
 +    Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
 +
 +    if (Status == STATUS_PENDING)
 +    {
 +        /* wait for the operation to complete */
 +        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
 +
 +       /* is object sync */
 +       if (FileObject->Flags & FO_SYNCHRONOUS_IO)
 +           Status = FileObject->FinalStatus;
 +       else
 +           Status = StatusBlock.Status;
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsSetInformationFile(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  PVOID FileInformation,
 +    IN  ULONG Length,
 +    IN  FILE_INFORMATION_CLASS FileInformationClass)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_OBJECT DeviceObject;
 +    PIRP Irp;
 +    PVOID Buffer;
 +    KEVENT Event;
 +    LARGE_INTEGER Offset;
 +    IO_STATUS_BLOCK IoStatus;
 +    NTSTATUS Status;
 +
 +    /* get related device object */
 +    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 +
 +    /* copy file information */
 +    Buffer = AllocateItem(NonPagedPool, Length);
 +    if (!Buffer)
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForRead(Buffer, Length, sizeof(UCHAR));
 +        RtlMoveMemory(Buffer, FileInformation, Length);
 +        Status = STATUS_SUCCESS;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        /* Exception, get the error code */
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END;
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* invalid user buffer */
 +        FreeItem(Buffer);
 +        return Status;
 +    }
 +
 +    /* initialize the event */
 +    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
 +
 +    /* zero offset */
 +    Offset.QuadPart = 0LL;
 +
 +    /* build the irp */
 +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus);
 +
 +    if (!Irp)
 +    {
 +        /* failed to allocate irp */
 +        FreeItem(Buffer);
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* get next stack location */
 +    IoStack = IoGetNextIrpStackLocation(Irp);
 +
 +    /* set irp parameters */
 +    IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass;
 +    IoStack->Parameters.SetFile.Length = Length;
 +    IoStack->Parameters.SetFile.FileObject = FileObject;
 +    Irp->AssociatedIrp.SystemBuffer = Buffer;
 +    Irp->UserBuffer = FileInformation;
 +
 +    /* dispatch the irp */
 +    Status = IoCallDriver(DeviceObject, Irp);
 +
 +    if (Status == STATUS_PENDING)
 +    {
 +        /* wait untill the operation has completed */
 +        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
 +        /* is a sync file object */
 +        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
 +            Status = FileObject->FinalStatus;
 +        else
 +            Status = IoStatus.Status;
 +    }
 +    /* done */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsStreamIo(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  PKEVENT Event OPTIONAL,
 +    IN  PVOID PortContext OPTIONAL,
 +    IN  PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
 +    IN  PVOID CompletionContext OPTIONAL,
 +    IN  KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL,
 +    OUT PIO_STATUS_BLOCK IoStatusBlock,
 +    IN  OUT PVOID StreamHeaders,
 +    IN  ULONG Length,
 +    IN  ULONG Flags,
 +    IN  KPROCESSOR_MODE RequestorMode)
 +{
 +    PIRP Irp;
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_OBJECT DeviceObject;
 +    NTSTATUS Status;
 +    LARGE_INTEGER Offset;
 +    PKSIOBJECT_HEADER ObjectHeader;
 +    BOOLEAN Ret;
 +
 +    /* get related device object */
 +    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 +    /* sanity check */
 +    ASSERT(DeviceObject != NULL);
 +
 +    /* is there a event provided */
 +    if (Event)
 +    {
 +        /* reset event */
 +        KeClearEvent(Event);
 +    }
 +
 +    if (RequestorMode || ExGetPreviousMode() == KernelMode)
 +    {
 +        /* requestor is from kernel land */
 +        ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
 +
 +        if (ObjectHeader)
 +        {
 +            /* there is a object header */
 +            if (Flags == KSSTREAM_READ)
 +            {
 +                /* is fast read supported */
 +                if (ObjectHeader->DispatchTable.FastRead)
 +                {
 +                    /* call fast read dispatch routine */
 +                    Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
 +
 +                    if (Ret)
 +                    {
 +                        /* the request was handeled */
 +                        return IoStatusBlock->Status;
 +                    }
 +                }
 +            }
 +            else if (Flags == KSSTREAM_WRITE)
 +            {
 +                /* is fast write supported */
 +                if (ObjectHeader->DispatchTable.FastWrite)
 +                {
 +                    /* call fast write dispatch routine */
 +                    Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
 +
 +                    if (Ret)
 +                    {
 +                        /* the request was handeled */
 +                        return IoStatusBlock->Status;
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    /* clear file object event */
 +    KeClearEvent(&FileObject->Event);
 +
 +    /* set the offset to zero */
 +    Offset.QuadPart = 0LL;
 +
 +    /* now build the irp */
 +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
 +                                       DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
 +    if (!Irp)
 +    {
 +        /* not enough memory */
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +    }
 +
 +    /* setup irp parameters */
 +    Irp->RequestorMode = RequestorMode;
 +    Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
 +    Irp->Tail.Overlay.OriginalFileObject = FileObject;
 +    Irp->UserBuffer = StreamHeaders;
 +
 +    /* get next irp stack location */
 +    IoStack = IoGetNextIrpStackLocation(Irp);
 +    /* setup stack parameters */
 +    IoStack->FileObject = FileObject;
 +    IoStack->Parameters.DeviceIoControl.InputBufferLength = Length;
 +    IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders;
 +    IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
 +
 +    if (CompletionRoutine)
 +    {
 +        /* setup completion routine for async processing */
 +        IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
 +    }
 +
 +    /* now call the driver */
 +    Status = IoCallDriver(DeviceObject, Irp);
 +    /* done */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsProbeStreamIrp(
 +    IN  PIRP Irp,
 +    IN  ULONG ProbeFlags,
 +    IN  ULONG HeaderSize)
 +{
 +    PMDL Mdl;
 +    PVOID Buffer;
 +    LOCK_OPERATION Operation;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    PKSSTREAM_HEADER StreamHeader;
 +    PIO_STACK_LOCATION IoStack;
 +    ULONG Length;
 +    BOOLEAN AllocateMdl = FALSE;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
 +
 +    if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer)
 +    {
 +        if (Irp->RequestorMode == KernelMode)
 +        {
 +            /* no need to allocate stream header */
 +            Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer;
 +        }
 +AllocMdl:
 +        /* check if alloc mdl flag is passed */
 +        if (!(ProbeFlags & KSPROBE_ALLOCATEMDL))
 +        {
 +            /* nothing more to do */
 +            return STATUS_SUCCESS;
 +        }
 +        if (Irp->MdlAddress)
 +        {
 +ProbeMdl:
 +            if (ProbeFlags & KSPROBE_PROBEANDLOCK)
 +            {
 +                if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL))
 +                {
 +                    if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
 +                    {
 +                        _SEH2_TRY
 +                        {
 +                            /* loop through all mdls and probe them */
 +                            Mdl = Irp->MdlAddress;
 +                            do
 +                            {
 +                                /* the mapping can fail */
 +                                Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
 +
 +                                if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
 +                                {
 +                                    /* no need to probe these pages */
 +                                    Buffer = Mdl->MappedSystemVa;
 +                                }
 +                                else
 +                                {
 +                                    /* probe that mdl */
 +                                    Buffer = MmMapLockedPages(Mdl, KernelMode);
 +                                }
 +
 +                                /* check if the mapping succeeded */
 +                                if (!Buffer)
 +                                {
 +                                    /* raise exception we'll catch */
 +                                    ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
 +                                }
 +
 +                                /* iterate to next mdl */
 +                                Mdl = Mdl->Next;
 +
 +                            }while(Mdl);
 +                        }
 +                        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +                        {
 +                            /* Exception, get the error code */
 +                            Status = _SEH2_GetExceptionCode();
 +                        } _SEH2_END;
 +                    }
 +                }
 +                else
 +                {
 +                    _SEH2_TRY
 +                    {
 +                        /* loop through all mdls and probe them */
 +                        Mdl = Irp->MdlAddress;
 +
 +                        /* determine operation */
 +                        if (!(ProbeFlags & KSPROBE_STREAMWRITE) || (ProbeFlags & KSPROBE_MODIFY))
 +                        {
 +                            /* operation is read / modify stream, need write access */
 +                            Operation = IoWriteAccess;
 +                        }
 +                        else
 +                        {
 +                            /* operation is write to device, so we need read access */
 +                            Operation = IoReadAccess;
 +                        }
 +
 +                        do
 +                        {
 +                            /* probe the pages */
 +                            MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
 +
 +                            if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
 +                            {
 +                                /* the mapping can fail */
 +                                Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
 +
 +                                if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
 +                                {
 +                                    /* no need to probe these pages */
 +                                    Buffer = Mdl->MappedSystemVa;
 +                                }
 +                                else
 +                                {
 +                                    /* probe that mdl */
 +                                    Buffer = MmMapLockedPages(Mdl, KernelMode);
 +                                }
 +
 +                                /* check if the mapping succeeded */
 +                                if (!Buffer)
 +                                {
 +                                    /* raise exception we'll catch */
 +                                    ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
 +                                }
 +                            }
 +
 +                            /* iterate to next mdl */
 +                            Mdl = Mdl->Next;
 +
 +                        }while(Mdl);
 +                    }
 +                    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +                    {
 +                        /* Exception, get the error code */
 +                        Status = _SEH2_GetExceptionCode();
 +                    } _SEH2_END;
 +                }
 +            }
 +            return Status;
 +        }
 +
 +        /* check all stream headers */
 +        StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
 +        ASSERT(StreamHeader);
 +        _SEH2_TRY
 +        {
 +            do
 +            {
 +                if (HeaderSize)
 +                {
 +                    /* does the supplied header size match stream header size and no type changed */
 +                    if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
 +                    {
 +                        /* invalid stream header */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +                }
 +                else
 +                {
 +                    /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
 +                    if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
 +                    {
 +                        /* invalid stream header */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +                }
 +
 +                if (Length < StreamHeader->Size)
 +                {
 +                    /* length is too short */
 +                    ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                }
 +
 +                if (ProbeFlags & KSPROBE_STREAMWRITE)
 +                {
 +                    if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
 +                    {
 +                        /* frame extend can never be smaller */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +
 +                    /* is this stream change packet */
 +                    if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
 +                    {
 +                        if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
 +                        {
 +                            /* stream changed - must be send in a single packet */
 +                            ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                        }
 +
 +                        if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
 +                        {
 +                            /* caller does not permit format changes */
 +                            ExRaiseStatus(STATUS_INVALID_PARAMETER);
 +                        }
 +
 +                        if (StreamHeader->FrameExtent)
 +                        {
 +                            /* allocate an mdl */
 +                            Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
 +
 +                            if (!Mdl)
 +                            {
 +                                /* not enough memory */
 +                                ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
 +                            }
 +
 +                            /* break-out to probe for the irp */
 +                            break;
 +                        }
 +                    }
 +                }
 +                else
 +                {
 +                    if (StreamHeader->DataUsed)
 +                    {
 +                        /* DataUsed must be zero for stream read operation */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +
 +                    if (StreamHeader->OptionsFlags)
 +                    {
 +                        /* no flags supported for reading */
 +                        ExRaiseStatus(STATUS_INVALID_PARAMETER);
 +                    }
 +                }
 +
 +                if (StreamHeader->FrameExtent)
 +                {
 +                    /* allocate an mdl */
 +                    ASSERT(Irp->MdlAddress == NULL);
 +                    Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
 +                    if (!Mdl)
 +                    {
 +                        /* not enough memory */
 +                        ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
 +                    }
 +                }
 +
 +                /* move to next stream header */
 +                Length -= StreamHeader->Size;
 +                StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
 +            }while(Length);
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            /* Exception, get the error code */
 +            Status = _SEH2_GetExceptionCode();
 +        }_SEH2_END;
 +
 +        /* now probe the allocated mdl's */
 +        if (!NT_SUCCESS(Status))
 +        {
 +            DPRINT("Status %x\n", Status);
 +            return Status;
 +        }
 +        else
 +            goto ProbeMdl;
 +    }
 +
 +    /* probe user mode buffers */
 +    if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
 +    {
 +        /* allocate stream header buffer */
 +        Irp->AssociatedIrp.SystemBuffer = AllocateItem(NonPagedPool, Length);
 +
 +        if (!Irp->AssociatedIrp.SystemBuffer)
 +        {
 +            /* no memory */
 +            return STATUS_INSUFFICIENT_RESOURCES;
 +        }
 +
 +        /* mark irp as buffered so that changes the stream headers are propagated back */
 +        Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
 +
 +        _SEH2_TRY
 +        {
 +            if (ProbeFlags & KSPROBE_STREAMWRITE)
 +            {
 +                if (ProbeFlags & KSPROBE_MODIFY)
 +                    ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
 +                else
 +                    ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR));
 +            }
 +            else
 +            {
 +                /* stream reads means writing */
 +                ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
 +
 +                /* set input operation flags */
 +                Irp->Flags |= IRP_INPUT_OPERATION;
 +            }
 +
 +            /* copy stream buffer */
 +            RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length);
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            /* Exception, get the error code */
 +            Status = _SEH2_GetExceptionCode();
 +        }_SEH2_END;
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            /* failed */
 +            return Status;
 +        }
 +
 +        if (ProbeFlags & KSPROBE_ALLOCATEMDL)
 +        {
 +            /* alloc mdls */
 +            goto AllocMdl;
 +        }
 +
 +        /* check all stream headers */
 +        StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
 +
 +        _SEH2_TRY
 +        {
 +            do
 +            {
 +                if (HeaderSize)
 +                {
 +                    /* does the supplied header size match stream header size and no type changed */
 +                    if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
 +                    {
 +                        /* invalid stream header */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +                }
 +                else
 +                {
 +                    /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
 +                    if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
 +                    {
 +                        /* invalid stream header */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +                }
 +
 +                if (Length < StreamHeader->Size)
 +                {
 +                    /* length is too short */
 +                    ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                }
 +
 +                if (ProbeFlags & KSPROBE_STREAMWRITE)
 +                {
 +                    if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
 +                    {
 +                        /* frame extend can never be smaller */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +
 +                    /* is this stream change packet */
 +                    if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
 +                    {
 +                        if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
 +                        {
 +                            /* stream changed - must be send in a single packet */
 +                            ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                        }
 +
 +                        if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
 +                        {
 +                            /* caller does not permit format changes */
 +                            ExRaiseStatus(STATUS_INVALID_PARAMETER);
 +                        }
 +
 +                        if (StreamHeader->FrameExtent)
 +                        {
 +                            /* allocate an mdl */
 +                            Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
 +
 +                            if (!Mdl)
 +                            {
 +                                /* not enough memory */
 +                                ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
 +                            }
 +
 +                            /* break out to probe for the irp */
 +                            AllocateMdl = TRUE;
 +                            break;
 +                        }
 +                    }
 +                }
 +                else
 +                {
 +                    if (StreamHeader->DataUsed)
 +                    {
 +                        /* DataUsed must be zero for stream read operation */
 +                        ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
 +                    }
 +
 +                    if (StreamHeader->OptionsFlags)
 +                    {
 +                        /* no flags supported for reading */
 +                        ExRaiseStatus(STATUS_INVALID_PARAMETER);
 +                    }
 +                }
 +
 +                /* move to next stream header */
 +                Length -= StreamHeader->Size;
 +                StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
 +            }while(Length);
 +
 +        }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            /* Exception, get the error code */
 +            Status = _SEH2_GetExceptionCode();
 +        }_SEH2_END;
 +
 +        /* now probe the allocated mdl's */
 +        if (NT_SUCCESS(Status))
 +            goto AllocMdl;
 +        else
 +            return Status;
 +    }
 +
 +    return STATUS_INVALID_BUFFER_SIZE;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsAllocateExtraData(
 +    IN  PIRP Irp,
 +    IN  ULONG ExtraSize,
 +    OUT PVOID* ExtraBuffer)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    ULONG Count, Index;
 +    PUCHAR Buffer, BufferOrg;
 +    PKSSTREAM_HEADER Header;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* sanity check */
 +    ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
 +
 +    /* get total length */
 +    Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
 +
 +    /* allocate buffer */
 +    Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
 +    if (!Buffer)
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +
 +    _SEH2_TRY
 +    {
 +        /* get input buffer */
 +        Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
 +        for(Index = 0; Index < Count; Index++)
 +        {
 +            /* copy stream header */
 +            RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
 +
 +            /* move to next header */
 +            Header++;
 +            /* increment output buffer offset */
 +            Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        /* Exception, get the error code */
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END;
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* free buffer on exception */
 +        FreeItem(Buffer);
 +        return Status;
 +    }
 +
 +    /* store result */
 +    *ExtraBuffer = BufferOrg;
 +
 +    /* done */
 +    return STATUS_SUCCESS;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsNullDriverUnload(
 +    IN  PDRIVER_OBJECT DriverObject)
 +{
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDispatchInvalidDeviceRequest(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    return STATUS_INVALID_DEVICE_REQUEST;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDefaultDeviceIoCompletion(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    NTSTATUS Status;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY && 
 +        IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
 +        IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
 +    {
 +        if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
 +        {
 +            /* fake success */
 +            Status = STATUS_SUCCESS;
 +        }
 +        else
 +        {
 +            /* request unsupported */
 +            Status = STATUS_INVALID_DEVICE_REQUEST;
 +        }
 +    }
 +    else
 +    {
 +        /* property / method / event not found */
 +        Status = STATUS_PROPSET_NOT_FOUND;
 +    }
 +
 +    /* complete request */
 +    Irp->IoStatus.Status = Status;
-     DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +BOOLEAN
 +NTAPI
 +KsDispatchFastIoDeviceControlFailure(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  BOOLEAN Wait,
 +    IN  PVOID InputBuffer  OPTIONAL,
 +    IN  ULONG InputBufferLength,
 +    OUT PVOID OutputBuffer  OPTIONAL,
 +    IN  ULONG OutputBufferLength,
 +    IN  ULONG IoControlCode,
 +    OUT PIO_STATUS_BLOCK IoStatus,
 +    IN  PDEVICE_OBJECT DeviceObject)
 +{
 +    return FALSE;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +BOOLEAN
 +NTAPI
 +KsDispatchFastReadFailure(
 +    IN  PFILE_OBJECT FileObject,
 +    IN  PLARGE_INTEGER FileOffset,
 +    IN  ULONG Length,
 +    IN  BOOLEAN Wait,
 +    IN  ULONG LockKey,
 +    OUT PVOID Buffer,
 +    OUT PIO_STATUS_BLOCK IoStatus,
 +    IN  PDEVICE_OBJECT DeviceObject)
 +{
 +    return FALSE;
 +}
 +
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsCancelIo(
 +    IN  OUT PLIST_ENTRY QueueHead,
 +    IN  PKSPIN_LOCK SpinLock)
 +{
 +    PDRIVER_CANCEL OldDriverCancel;
 +    PIO_STACK_LOCATION IoStack;
 +    PLIST_ENTRY Entry;
 +    PLIST_ENTRY NextEntry;
 +    PIRP Irp;
 +    KIRQL OldLevel;
 +
 +    /* acquire spinlock */
 +    KeAcquireSpinLock(SpinLock, &OldLevel);
 +    /* point to first entry */
 +    Entry = QueueHead->Flink;
 +    /* loop all items */
 +    while(Entry != QueueHead)
 +    {
 +        /* get irp offset */
 +        Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
 +
 +        /* get next entry */
 +        NextEntry = Entry->Flink;
 +
 +        /* set cancelled bit */
 +        Irp->Cancel = TRUE;
 +
 +        /* now set the cancel routine */
 +        OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
 +        if (OldDriverCancel)
 +        {
 +            /* this irp hasnt been yet used, so free to cancel */
 +            KeReleaseSpinLock(SpinLock, OldLevel);
 +
 +            /* get current irp stack */
 +            IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +            /* acquire cancel spinlock */
 +            IoAcquireCancelSpinLock(&Irp->CancelIrql);
 +
 +            /* call provided cancel routine */
 +            OldDriverCancel(IoStack->DeviceObject, Irp);
 +
 +            /* re-acquire spinlock */
 +            KeAcquireSpinLock(SpinLock, &OldLevel);
 +        }
 +
 +        /* move on to next entry */
 +        Entry = NextEntry;
 +    }
 +
 +    /* the irp has already been canceled */
 +    KeReleaseSpinLock(SpinLock, OldLevel);
 +
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsReleaseIrpOnCancelableQueue(
 +    IN  PIRP Irp,
 +    IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
 +{
 +    PKSPIN_LOCK SpinLock;
 +    PDRIVER_CANCEL OldDriverCancel;
 +    PIO_STACK_LOCATION IoStack;
 +    KIRQL OldLevel;
 +
 +    /* check for required parameters */
 +    if (!Irp)
 +        return;
 +
 +    if (!DriverCancel)
 +    {
 +        /* default to KsCancelRoutine */
 +        DriverCancel = KsCancelRoutine;
 +    }
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* get internal queue lock */
 +    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
 +
 +    /* acquire spinlock */
 +    KeAcquireSpinLock(SpinLock, &OldLevel);
 +
 +    /* now set the cancel routine */
 +    OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
 +
 +    if (Irp->Cancel && OldDriverCancel == NULL)
 +    {
 +        /* the irp has already been canceled */
 +        KeReleaseSpinLock(SpinLock, OldLevel);
 +
 +        /* cancel routine requires that cancel spinlock is held */
 +        IoAcquireCancelSpinLock(&Irp->CancelIrql);
 +
 +        /* cancel irp */
 +        DriverCancel(IoStack->DeviceObject, Irp);
 +    }
 +    else
 +    {
 +        /* done */
 +        KeReleaseSpinLock(SpinLock, OldLevel);
 +    }
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +PIRP
 +NTAPI
 +KsRemoveIrpFromCancelableQueue(
 +    IN  OUT PLIST_ENTRY QueueHead,
 +    IN  PKSPIN_LOCK SpinLock,
 +    IN  KSLIST_ENTRY_LOCATION ListLocation,
 +    IN  KSIRP_REMOVAL_OPERATION RemovalOperation)
 +{
 +    PIRP Irp;
 +    PLIST_ENTRY CurEntry;
 +    KIRQL OldIrql;
 +
 +    DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
 +
 +    /* check parameters */
 +    if (!QueueHead || !SpinLock)
 +        return NULL;
 +
 +    /* check if parameter ListLocation is valid */
 +    if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead)
 +        return NULL;
 +
 +    /* acquire list lock */
 +    KeAcquireSpinLock(SpinLock, &OldIrql);
 +
 +    /* point to queue head */
 +    CurEntry = QueueHead;
 +
 +    do
 +    {
 +        /* reset irp to null */
 +        Irp = NULL;
 +
 +        /* iterate to next entry */
 +        if (ListLocation == KsListEntryHead)
 +            CurEntry = CurEntry->Flink;
 +        else
 +            CurEntry = CurEntry->Blink;
 +
 +        /* is the end of list reached */
 +        if (CurEntry == QueueHead)
 +        {
 +            /* reached end of list */
 +            break;
 +        }
 +
 +        /* get irp offset */
 +        Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
 +
 +        if (Irp->Cancel)
 +        {
 +            /* irp has been canceled */
 +            break;
 +        }
 +
 +        if (Irp->CancelRoutine)
 +        {
 +            /* remove cancel routine */
 +            Irp->CancelRoutine = NULL;
 +
 +            if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
 +            {
 +                /* remove irp from list */
 +                RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 +            }
 +
 +            if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem)
 +                break;
 +        }
 +
 +    }while(TRUE);
 +
 +    /* release lock */
 +    KeReleaseSpinLock(SpinLock, OldIrql);
 +
 +    if (!Irp || Irp->CancelRoutine == NULL)
 +    {
 +        /* either an irp has been acquired or nothing found */
 +        return Irp;
 +    }
 +
 +    /* time to remove the canceled irp */
 +    IoAcquireCancelSpinLock(&OldIrql);
 +    /* acquire list lock */
 +    KeAcquireSpinLockAtDpcLevel(SpinLock);
 +
 +    if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
 +    {
 +        /* remove it */
 +        RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 +    }
 +
 +    /* release list lock */
 +    KeReleaseSpinLockFromDpcLevel(SpinLock);
 +
 +    /* release cancel spinlock */
 +    IoReleaseCancelSpinLock(OldIrql);
 +    /* no non canceled irp has been found */
 +    return NULL;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsMoveIrpsOnCancelableQueue(
 +    IN  OUT PLIST_ENTRY SourceList,
 +    IN  PKSPIN_LOCK SourceLock,
 +    IN  OUT PLIST_ENTRY DestinationList,
 +    IN  PKSPIN_LOCK DestinationLock OPTIONAL,
 +    IN  KSLIST_ENTRY_LOCATION ListLocation,
 +    IN  PFNKSIRPLISTCALLBACK ListCallback,
 +    IN  PVOID Context)
 +{
 +    KIRQL OldLevel;
 +    PLIST_ENTRY SrcEntry;
 +    PIRP Irp;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +
 +    if (!DestinationLock)
 +    {
 +        /* no destination lock just acquire the source lock */
 +        KeAcquireSpinLock(SourceLock, &OldLevel);
 +    }
 +    else
 +    {
 +        /* acquire cancel spinlock */
 +        IoAcquireCancelSpinLock(&OldLevel);
 +
 +        /* now acquire source lock */
 +        KeAcquireSpinLockAtDpcLevel(SourceLock);
 +
 +        /* now acquire destination lock */
 +        KeAcquireSpinLockAtDpcLevel(DestinationLock);
 +    }
 +
 +    /* point to list head */
 +    SrcEntry = SourceList;
 +
 +    /* now move all irps */
 +    while(TRUE)
 +    {
 +        if (ListLocation == KsListEntryTail)
 +        {
 +            /* move queue downwards */
 +            SrcEntry = SrcEntry->Flink;
 +        }
 +        else
 +        {
 +            /* move queue upwards */
 +            SrcEntry = SrcEntry->Blink;
 +        }
 +
 +        if (SrcEntry == SourceList)
 +        {
 +            /* eof list reached */
 +            break;
 +        }
 +
 +        /* get irp offset */
 +        Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
 +
 +        /* now check if irp can be moved */
 +        Status = ListCallback(Irp, Context);
 +
 +        /* check if irp can be moved */
 +        if (Status == STATUS_SUCCESS)
 +        {
 +            /* remove irp from src list */
 +            RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 +
 +            if (ListLocation == KsListEntryTail)
 +            {
 +                /* insert irp end of list */
 +                InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
 +            }
 +            else
 +            {
 +                /* insert irp head of list */
 +                InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
 +            }
 +
 +            /* do we need to update the irp lock */
 +            if (DestinationLock)
 +            {
 +                /* update irp lock */
 +                KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
 +            }
 +        }
 +        else
 +        {
 +            if (Status != STATUS_NO_MATCH)
 +            {
 +                /* callback decided to stop enumeration */
 +                break;
 +            }
 +
 +            /* reset return value */
 +            Status = STATUS_SUCCESS;
 +        }
 +    }
 +
 +    if (!DestinationLock)
 +    {
 +        /* release source lock */
 +        KeReleaseSpinLock(SourceLock, OldLevel);
 +    }
 +    else
 +    {
 +        /* now release destination lock */
 +        KeReleaseSpinLockFromDpcLevel(DestinationLock);
 +
 +        /* now release source lock */
 +        KeReleaseSpinLockFromDpcLevel(SourceLock);
 +
 +
 +        /* now release cancel spinlock */
 +        IoReleaseCancelSpinLock(OldLevel);
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsRemoveSpecificIrpFromCancelableQueue(
 +    IN  PIRP Irp)
 +{
 +    PKSPIN_LOCK SpinLock;
 +    KIRQL OldLevel;
 +
 +    DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp);
 +
 +    /* get internal queue lock */
 +    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
 +
 +    /* acquire spinlock */
 +    KeAcquireSpinLock(SpinLock, &OldLevel);
 +
 +    /* remove the irp from the list */
 +    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 +
 +    /* release spinlock */
 +    KeReleaseSpinLock(SpinLock, OldLevel);
 +}
 +
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsAddIrpToCancelableQueue(
 +    IN  OUT PLIST_ENTRY QueueHead,
 +    IN  PKSPIN_LOCK SpinLock,
 +    IN  PIRP Irp,
 +    IN  KSLIST_ENTRY_LOCATION ListLocation,
 +    IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
 +{
 +    PDRIVER_CANCEL OldDriverCancel;
 +    PIO_STACK_LOCATION IoStack;
 +    KIRQL OldLevel;
 +
 +    /* check for required parameters */
 +    if (!QueueHead || !SpinLock || !Irp)
 +        return;
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++    DPRINT1("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
 +
 +    // HACK for ms portcls
 +    if (IoStack->MajorFunction == IRP_MJ_CREATE)
 +    {
 +        // complete the request
++        DPRINT1("MS HACK\n");
 +        Irp->IoStatus.Status = STATUS_SUCCESS;
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +        return;
 +    }
 +
 +
 +    if (!DriverCancel)
 +    {
 +        /* default to KsCancelRoutine */
 +        DriverCancel = KsCancelRoutine;
 +    }
 +
 +
 +    /* acquire spinlock */
 +    KeAcquireSpinLock(SpinLock, &OldLevel);
 +
 +    if (ListLocation == KsListEntryTail)
 +    {
 +        /* insert irp to tail of list */
 +        InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
 +    }
 +    else
 +    {
 +        /* insert irp to head of list */
 +        InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
 +    }
 +
 +    /* store internal queue lock */
 +    KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
 +
 +    /* now set the cancel routine */
 +    OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
 +
 +    if (Irp->Cancel && OldDriverCancel == NULL)
 +    {
 +        /* the irp has already been canceled */
 +        KeReleaseSpinLock(SpinLock, OldLevel);
 +
 +        /* cancel routine requires that cancel spinlock is held */
 +        IoAcquireCancelSpinLock(&Irp->CancelIrql);
 +
 +        /* cancel irp */
 +        DriverCancel(IoStack->DeviceObject, Irp);
 +    }
 +    else
 +    {
 +        /* done */
 +        KeReleaseSpinLock(SpinLock, OldLevel);
 +    }
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +VOID
 +NTAPI
 +KsCancelRoutine(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    PKSPIN_LOCK SpinLock;
 +
 +    /* get internal queue lock */
 +    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
 +
 +    /* acquire spinlock */
 +    KeAcquireSpinLockAtDpcLevel(SpinLock);
 +
 +    /* sanity check */
 +    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
 +
 +    /* release cancel spinlock */
 +    IoReleaseCancelSpinLock(Irp->CancelIrql);
 +
 +    /* remove the irp from the list */
 +    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 +
 +    /* release spinlock */
 +    KeReleaseSpinLock(SpinLock, Irp->CancelIrql);
 +
 +    /* has the irp already been canceled */
 +    if (Irp->IoStatus.Status != STATUS_CANCELLED)
 +    {
 +        /* let's complete it */
 +        Irp->IoStatus.Status = STATUS_CANCELLED;
-         ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +    }
 +}
 +
 +NTSTATUS
 +FindMatchingCreateItem(
 +    PLIST_ENTRY ListHead,
 +    ULONG BufferSize,
 +    LPWSTR Buffer,
 +    OUT PCREATE_ITEM_ENTRY *OutCreateItem)
 +{
 +    PLIST_ENTRY Entry;
 +    PCREATE_ITEM_ENTRY CreateItemEntry;
 +    UNICODE_STRING RefString;
 +    LPWSTR pStr;
 +
 +    /* get terminator */
 +    pStr = wcschr(Buffer, L'\\');
 +
 +    /* sanity check */
 +    ASSERT(pStr != NULL);
 +
 +    if (pStr == Buffer)
 +    {
 +        // skip slash
 +        RtlInitUnicodeString(&RefString, ++pStr);
 +    }
 +    else
 +    {
 +        // request is for pin / node / allocator
 +        RefString.Buffer = Buffer;
 +        RefString.Length = BufferSize = RefString.MaximumLength = ((ULONG_PTR)pStr - (ULONG_PTR)Buffer);
 +    }
 +
 +    /* point to first entry */
 +    Entry = ListHead->Flink;
 +
 +    /* loop all device items */
 +    while(Entry != ListHead)
 +    {
 +        /* get create item entry */
 +        CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
 +
 +        ASSERT(CreateItemEntry->CreateItem);
 +
 +        if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
 +        {
 +            /* create item is default */
 +            *OutCreateItem = CreateItemEntry;
 +            return STATUS_SUCCESS;
 +        }
 +
 +        if (!CreateItemEntry->CreateItem->Create)
 +        {
 +            /* skip free create item */
 +            Entry = Entry->Flink;
 +            continue;
 +        }
 +
-                                                            BufferSize);
 +        DPRINT("CreateItem %S Length %u Request %wZ %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
 +                                                           CreateItemEntry->CreateItem->ObjectClass.Length,
 +                                                           &RefString,
-         if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
++                                                           RefString.Length);
 +
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length)
 +        {
 +            /* create item doesnt match in length */
 +            Entry = Entry->Flink;
 +            continue;
 +        }
 +
 +         /* now check if the object class is the same */
 +        if (!RtlCompareUnicodeString(&CreateItemEntry->CreateItem->ObjectClass, &RefString, TRUE))
 +        {
 +            /* found matching create item */
 +            *OutCreateItem = CreateItemEntry;
 +            return STATUS_SUCCESS;
 +        }
 +        /* iterate to next */
 +        Entry = Entry->Flink;
 +    }
 +
 +    return STATUS_NOT_FOUND;
 +}
 +
 +NTSTATUS
 +NTAPI
 +KspCreate(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    PCREATE_ITEM_ENTRY CreateItemEntry;
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_EXTENSION DeviceExtension;
 +    PKSIDEVICE_HEADER DeviceHeader;
 +    PKSIOBJECT_HEADER ObjectHeader;
 +    NTSTATUS Status;
 +
 +    DPRINT("KS / CREATE\n");
 +
 +    /* get current stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +    /* get device extension */
 +    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +    /* get device header */
 +    DeviceHeader = DeviceExtension->DeviceHeader;
 +
 +
 +    if (IoStack->FileObject->FileName.Buffer == NULL)
 +    {
 +        /* FIXME Pnp-Issue */
 +        DPRINT("Using reference string hack\n");
 +        Irp->IoStatus.Information = 0;
 +        /* set return status */
 +        Irp->IoStatus.Status = STATUS_SUCCESS;
-     IoCompleteRequest(Irp, IO_NO_INCREMENT);
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +        return STATUS_SUCCESS;
 +    }
 +
 +    if (IoStack->FileObject->RelatedFileObject != NULL)
 +    {
 +        /* request is to instantiate a pin / node / clock / allocator */
 +        ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
 +
 +        /* sanity check */
 +        ASSERT(ObjectHeader);
 +
 +        /* find a matching a create item */
 +        Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
 +    }
 +    else
 +    {
 +        /* request to create a filter */
 +        Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
 +    }
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* set object create item */
 +        KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
 +
 +        /* call create function */
 +        Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
 +
 +        if (NT_SUCCESS(Status))
 +        {
 +            /* increment create item reference count */
 +            InterlockedIncrement(&CreateItemEntry->ReferenceCount);
 +        }
 +        return Status;
 +    }
 +
 +    Irp->IoStatus.Information = 0;
 +    /* set return status */
 +    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++    CompleteRequest(Irp, IO_NO_INCREMENT);
 +    return STATUS_UNSUCCESSFUL;
 +}
 +
 +NTSTATUS
 +NTAPI
 +KspDispatchIrp(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_EXTENSION DeviceExtension;
 +    PKSIOBJECT_HEADER ObjectHeader;
 +    PKSIDEVICE_HEADER DeviceHeader;
 +    PDRIVER_DISPATCH Dispatch;
 +    NTSTATUS Status;
 +
 +    /* get current stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    /* get device extension */
 +    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +    /* get device header */
 +    DeviceHeader = DeviceExtension->DeviceHeader;
 +
 +    ASSERT(IoStack->FileObject);
 +
 +    /* get object header */
 +    ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2;
 +
 +    if (!ObjectHeader)
 +    {
 +        /* FIXME Pnp-Issue*/
 +        Irp->IoStatus.Status = STATUS_SUCCESS;
 +        Irp->IoStatus.Information = 0;
 +        /* complete and forget */
++        CompleteRequest(Irp, IO_NO_INCREMENT);
 +        return STATUS_SUCCESS;
 +    }
 +
 +    /* sanity check */
 +    ASSERT(ObjectHeader);
 +    /* store create item */
 +    //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
 +
 +    /* retrieve matching dispatch function */
 +    switch(IoStack->MajorFunction)
 +    {
 +        case IRP_MJ_CLOSE:
 +            Dispatch = ObjectHeader->DispatchTable.Close;
 +            break;
 +        case IRP_MJ_DEVICE_CONTROL:
 +            Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
 +            break;
 +        case IRP_MJ_READ:
 +            Dispatch = ObjectHeader->DispatchTable.Read;
 +            break;
 +        case IRP_MJ_WRITE:
 +            Dispatch = ObjectHeader->DispatchTable.Write;
 +            break;
 +        case IRP_MJ_FLUSH_BUFFERS :
 +            Dispatch = ObjectHeader->DispatchTable.Flush;
 +            break;
 +        case IRP_MJ_QUERY_SECURITY:
 +            Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
 +            break;
 +        case IRP_MJ_SET_SECURITY:
 +            Dispatch = ObjectHeader->DispatchTable.SetSecurity;
 +            break;
 +        case IRP_MJ_PNP:
 +            Dispatch = KsDefaultDispatchPnp;
 +        default:
 +            Dispatch = NULL;
 +    }
 +
 +    /* is the request supported */
 +    if (Dispatch)
 +    {
 +        /* now call the dispatch function */
 +        Status = Dispatch(DeviceObject, Irp);
 +    }
 +    else
 +    {
 +        /* not supported request */
 +        Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsSetMajorFunctionHandler(
 +    IN  PDRIVER_OBJECT DriverObject,
 +    IN  ULONG MajorFunction)
 +{
 +    DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
 +
 +    switch ( MajorFunction )
 +    {
 +        case IRP_MJ_CREATE:
 +            DriverObject->MajorFunction[MajorFunction] = KspCreate;
 +            break;
 +        case IRP_MJ_DEVICE_CONTROL:
 +        case IRP_MJ_CLOSE:
 +        case IRP_MJ_READ:
 +        case IRP_MJ_WRITE:
 +        case IRP_MJ_FLUSH_BUFFERS :
 +        case IRP_MJ_QUERY_SECURITY:
 +        case IRP_MJ_SET_SECURITY:
 +            DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
 +            break;
 +        default:
 +            DPRINT1("NotSupported %x\n", MajorFunction);
 +            return STATUS_INVALID_PARAMETER;
 +    };
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +/*
 +    @implemented
 +*/
 +KSDDKAPI
 +NTSTATUS
 +NTAPI
 +KsDispatchIrp(
 +    IN  PDEVICE_OBJECT DeviceObject,
 +    IN  PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
 +    PKSIDEVICE_HEADER DeviceHeader;
 +    PDEVICE_EXTENSION DeviceExtension;
 +
 +    DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
 +
 +    /* get device extension */
 +    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
++
 +    /* get device header */
 +    DeviceHeader = DeviceExtension->DeviceHeader;
 +
 +
 +    /* get current irp stack */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
 +    {
 +        if (IoStack->MajorFunction == IRP_MJ_CREATE)
 +        {
 +            /* check internal type */
 +            if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
 +            {
 +                /* AVStream client */
 +                return IKsDevice_Create(DeviceObject, Irp);
 +            }
 +            else
 +            {
 +                /* external client (portcls) */
 +                return KspCreate(DeviceObject, Irp);
 +            }
 +        }
 +
 +        switch (IoStack->MajorFunction)
 +        {
 +            case IRP_MJ_CLOSE:
 +            case IRP_MJ_READ:
 +            case IRP_MJ_WRITE:
 +            case IRP_MJ_FLUSH_BUFFERS:
 +            case IRP_MJ_QUERY_SECURITY:
 +            case IRP_MJ_SET_SECURITY:
 +            case IRP_MJ_PNP:
 +            case IRP_MJ_DEVICE_CONTROL:
 +                return KspDispatchIrp(DeviceObject, Irp);
 +            default:
 +                return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
 +        }
 +    }
 +
 +    /* dispatch power */
 +    if (IoStack->MajorFunction == IRP_MJ_POWER)
 +    {
 +        /* check internal type */
 +        if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
 +        {
 +            /* AVStream client */
 +            return IKsDevice_Power(DeviceObject, Irp);
 +        }
 +        else
 +        {
 +            /* external client (portcls) */
 +            return KsDefaultDispatchPower(DeviceObject, Irp);
 +        }
 +    }
 +    else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
 +    {
 +        /* check internal type */
 +        if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
 +        {
 +            /* AVStream client */
 +            return IKsDevice_Pnp(DeviceObject, Irp);
 +        }
 +        else
 +        {
 +            /* external client (portcls) */
 +            return KsDefaultDispatchPnp(DeviceObject, Irp);
 +        }
 +    }
 +    else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
 +    {
 +        /* forward irp */
 +        return KsDefaultForwardIrp(DeviceObject, Irp);
 +    }
 +    else
 +    {
 +        /* not supported */
 +        return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
 +    }
 +}
 +
 +/*
 +    @unimplemented
 +*/
 +KSDDKAPI
 +ULONG
 +NTAPI
 +KsGetNodeIdFromIrp(
 +    IN PIRP Irp)
 +{
 +    UNIMPLEMENTED
 +    return KSFILTER_NODE;
 +}
 +
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,08d5286..08d5286
mode 000000,100644..100644
--- /dev/null
index 459e60b,0000000..c2aeaad
mode 100644,000000..100644
--- /dev/null
@@@ -1,309 -1,0 +1,432 @@@
-     UNIMPLEMENTED;
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Kernel Streaming
 + * FILE:            drivers/ksfilter/swenum/swenum.c
 + * PURPOSE:         KS Allocator functions
 + * PROGRAMMER:      Johannes Anderwald
 + */
 +
 +
 +#include "precomp.h"
 +
 +const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 +
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchPower(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
++    NTSTATUS Status, PnpStatus;
++    BOOLEAN ChildDevice;
++    PIO_STACK_LOCATION IoStack;
++    PDEVICE_OBJECT PnpDeviceObject = NULL;
++
++    /* get current stack location */
++    IoStack = IoGetCurrentIrpStackLocation(Irp);
++
++    /* check if the device object is a child device */
++    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
++
++    /* get bus enum pnp object */
++    PnpStatus = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
++
++    /* check for success */
++    if (!NT_SUCCESS(Status) || !NT_SUCCESS(PnpStatus))
++    {
++        /* start next power irp */
++        PoStartNextPowerIrp(Irp);
++
++        /* just complete the irp */
++        Irp->IoStatus.Status = STATUS_SUCCESS;
++
++        /* complete the irp */
++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++
++        /* done */
++        return STATUS_SUCCESS;
++    }
++
++    if (IoStack->MinorFunction == IRP_MN_SET_POWER || IoStack->MinorFunction == IRP_MN_QUERY_POWER)
++    {
++        /* fake success */
++        Irp->IoStatus.Status = STATUS_SUCCESS;
++    }
 +
++    if (!ChildDevice)
++    {
++        /* forward to pnp device object */
++        PoStartNextPowerIrp(Irp);
++
++        /* skip current location */
++        IoSkipCurrentIrpStackLocation(Irp);
++
++        /* done */
++        return PoCallDriver(PnpDeviceObject, Irp);
++    }
++
++    /* start next power irp */
++    PoStartNextPowerIrp(Irp);
 +
 +    /* just complete the irp */
 +    Irp->IoStatus.Status = STATUS_SUCCESS;
 +
 +    /* complete the irp */
 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    /* done */
 +    return STATUS_SUCCESS;
-     if (!NT_SUCCESS(Status))
 +}
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchPnp(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    NTSTATUS Status;
 +    BOOLEAN ChildDevice;
 +    PIO_STACK_LOCATION IoStack;
 +    PDEVICE_OBJECT PnpDeviceObject = NULL;
 +
++    /* get current stack location */
++    IoStack = IoGetCurrentIrpStackLocation(Irp);
++
 +    /* check if the device object is a child device */
 +    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
 +
 +    /* check for success */
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        Irp->IoStatus.Status = Status;
 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +        return Status;
 +    }
 +
++    DPRINT("SwDispatchPnp ChildDevice %u Request %x\n", ChildDevice, IoStack->MinorFunction);
++
 +    /* let ks handle it */
 +    Status = KsServiceBusEnumPnpRequest(DeviceObject, Irp);
 +
-     /* skip current location */
-     IoSkipCurrentIrpStackLocation(Irp);
-     /* call the pnp device object */
-     return IoCallDriver(PnpDeviceObject, Irp);
++    /* check if the request was for a pdo */
++    if (!ChildDevice)
++    {
++        if (Status != STATUS_NOT_SUPPORTED)
++        {
++            /* store result */
++            Irp->IoStatus.Status = Status;
++        }
++
++        /* complete request */
++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++
++        /* done */
++        return Status;
++    }
++
++    DPRINT("SwDispatchPnp KsServiceBusEnumPnpRequest Status %x\n", Status);
++
++    if (NT_SUCCESS(Status))
 +    {
 +        /* invalid request or not supported */
 +        Irp->IoStatus.Status = Status;
 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +        return Status;
 +    }
 +
 +    /* get bus enum pnp object */
 +    Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
 +
++    DPRINT("SwDispatchPnp KsGetBusEnumPnpDeviceObject Status %x\n", Status);
++
 +    /* check for success */
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed to get pnp object */
 +        Irp->IoStatus.Status = Status;
 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +        return Status;
 +    }
 +
 +    /* sanity check */
 +    ASSERT(PnpDeviceObject);
 +
 +    /* get current stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
 +    {
 +        /* delete the device */
 +        IoDeleteDevice(DeviceObject);
 +    }
++    else
++    {
++        if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES || IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
++        {
++            /* no resources required */
++            Irp->IoStatus.Information = 0;
++            Irp->IoStatus.Status = STATUS_SUCCESS;
++
++            /* skip current location */
++            IoSkipCurrentIrpStackLocation(Irp);
++
++            /* call the pnp device object */
++            return IoCallDriver(PnpDeviceObject, Irp);
++        }
++
++        if (IoStack->MajorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
++        {
++            /* device cannot be disabled */
++            Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
++            Irp->IoStatus.Status = STATUS_SUCCESS;
++
++            /* skip current location */
++            IoSkipCurrentIrpStackLocation(Irp);
++
++            /* call the pnp device object */
++            return IoCallDriver(PnpDeviceObject, Irp);
++        }
 +
-     NTSTATUS Status = STATUS_SUCCESS;
++        if (Status == STATUS_NOT_SUPPORTED)
++        {
++            /* skip current location */
++            IoSkipCurrentIrpStackLocation(Irp);
++
++            /* call the pnp device object */
++            return IoCallDriver(PnpDeviceObject, Irp);
++        }
++    }
++
++    /* complete the request */
++    Irp->IoStatus.Status = Status;
++    IoCompleteRequest(Irp, IO_NO_INCREMENT);
++
++    return Status;
 +}
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchSystemControl(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    NTSTATUS Status;
 +    BOOLEAN ChildDevice;
 +    PDEVICE_OBJECT PnpDeviceObject;
 +
 +    /* check if the device object is a child device */
 +    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
 +
 +    /* check for success */
 +    if (NT_SUCCESS(Status))
 +    {
 +        if (!ChildDevice)
 +        {
 +            /* bus devices dont support internal requests */
 +            Irp->IoStatus.Status = STATUS_SUCCESS;
 +            IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +            return STATUS_SUCCESS;
 +        }
 +
 +        /* get bus enum pnp object */
 +        Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
 +
 +        /* check for success */
 +        if (NT_SUCCESS(Status))
 +        {
 +            /* skip current location */
 +            IoSkipCurrentIrpStackLocation(Irp);
 +            /* call the pnp device object */
 +            return IoCallDriver(PnpDeviceObject, Irp);
 +        }
 +
 +    }
 +
 +    /* complete the request */
 +    Irp->IoStatus.Status = Status;
 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    return Status;
 +
 +}
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchDeviceControl(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    PIO_STACK_LOCATION IoStack;
-         return KsGetBusEnumIdentifier(Irp);
++    NTSTATUS Status;
 +
 +    /* get current stack location */
 +    IoStack = IoGetCurrentIrpStackLocation(Irp);
 +
 +    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_INSTALL_INTERFACE)
 +    {
 +        /* install interface */
 +        Status = KsInstallBusEnumInterface(Irp);
++        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_INSTALL_INTERFACE %x\n", Status);
 +    }
 +    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_REMOVE_INTERFACE)
 +    {
 +        /* remove interface */
 +        Status = KsRemoveBusEnumInterface(Irp);
++        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_REMOVE_INTERFACE %x\n", Status);
++
 +    }
 +    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_GET_BUS_ID)
 +    {
 +        /* get bus id */
++        Status = KsGetBusEnumIdentifier(Irp);
++        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_GET_BUS_ID %x\n", Status);
++    }
++    else
++    {
++        DPRINT("SwDispatchDeviceControl Unknown IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
++        Status = STATUS_INVALID_PARAMETER;
 +    }
 +
 +    /* store result */
 +    Irp->IoStatus.Status = Status;
 +
 +    /* complete irp */
 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    /* done */
 +    return Status;
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchCreate(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    NTSTATUS Status;
 +    BOOLEAN ChildDevice;
 +
 +    /* check if the device object is a child device */
 +    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
 +
++    DPRINT("SwDispatchCreate %x\n", Status);
++
 +    /* check for success */
 +    if (NT_SUCCESS(Status))
 +    {
 +        if (ChildDevice)
 +        {
 +            /* child devices cant create devices */
 +            Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
 +            IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +            return STATUS_OBJECT_NAME_NOT_FOUND;
 +        }
 +        /* perform the create request */
 +        Status = KsServiceBusEnumCreateRequest(DeviceObject, Irp);
++        DPRINT("SwDispatchCreate %x\n", Status);
 +    }
 +
 +    /* check the irp is pending */
 +    if (Status != STATUS_PENDING)
 +    {
 +        /* irp is ok to complete */
 +        Irp->IoStatus.Status = Status;
 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +    }
 +
 +    return Status;
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +SwDispatchClose(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    /* just complete the irp */
 +    Irp->IoStatus.Status = STATUS_SUCCESS;
 +
 +    /* complete the irp */
 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    /* done */
 +    return STATUS_SUCCESS;
 +
 +}
 +
 +NTSTATUS
 +NTAPI
 +SwAddDevice(
 +    IN PDRIVER_OBJECT DriverObject,
 +    IN PDEVICE_OBJECT PhysicalDeviceObject)
 +{
 +    NTSTATUS Status;
 +    PDEVICE_OBJECT FunctionalDeviceObject;
 +
++    DPRINT("SWENUM AddDevice\n");
 +    /* create the device */
 +    Status = IoCreateDevice(DriverObject, sizeof(KSDEVICE_HEADER), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &FunctionalDeviceObject);
 +
 +    if (!NT_SUCCESS(Status))
 +    {
 +        /* failed */
 +        return Status;
 +    }
 +
 +    /* create the bus enum object */
 +    Status = KsCreateBusEnumObject(L"SW", FunctionalDeviceObject, PhysicalDeviceObject, NULL, &KSMEDIUMSETID_Standard, L"Devices");
 +
 +    /* check for success */
 +    if (NT_SUCCESS(Status))
 +    {
 +        /* set device flags */
 +        FunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
 +        FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
 +    }
 +    else
 +    {
 +        /* failed to create bus enum object */
 +        IoDeleteDevice(FunctionalDeviceObject);
 +    }
 +
 +    /* done */
 +    return Status;
 +}
 +
 +VOID
 +NTAPI
 +SwUnload(
 +    IN  PDRIVER_OBJECT DriverObject)
 +{
 +    /* nop */
 +}
 +
 +NTSTATUS
 +NTAPI
 +DriverEntry(
 +    IN PDRIVER_OBJECT DriverObject,
 +    IN PUNICODE_STRING RegistryPathName)
 +{
 +
 +    /* setup add device routine */
 +    DriverObject->DriverExtension->AddDevice = SwAddDevice;
 +
 +    /* setup unload routine */
 +    DriverObject->DriverUnload = SwUnload;
 +
 +    /* misc irp handling routines */
 +    DriverObject->MajorFunction[IRP_MJ_CREATE] = SwDispatchCreate;
 +    DriverObject->MajorFunction[IRP_MJ_CLOSE] = SwDispatchClose;
 +    DriverObject->MajorFunction[IRP_MJ_PNP] = SwDispatchPnp;
 +    DriverObject->MajorFunction[IRP_MJ_POWER] = SwDispatchPower;
 +    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SwDispatchDeviceControl;
 +    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SwDispatchSystemControl;
 +
++    DPRINT("SWENUM loaded\n");
 +    return STATUS_SUCCESS;
 +}
 +