[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / irp.c
index f46bbb1..0c6036e 100644 (file)
 /*
-    ReactOS Kernel Streaming
-    IRP Helpers
-*/
+ * 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"
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsAcquireResetValue(
-    IN  PIRP Irp,
-    OUT KSRESET* ResetValue)
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsDispatchQuerySecurity(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    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);
+        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);
+    return Status;
 }
 
 /*
     @implemented
 */
 KSDDKAPI
-VOID
+NTSTATUS
 NTAPI
-KsAddIrpToCancelableQueue(
-    IN  OUT PLIST_ENTRY QueueHead,
-    IN  PKSPIN_LOCK SpinLock,
-    IN  PIRP Irp,
-    IN  KSLIST_ENTRY_LOCATION ListLocation,
-    IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
+KsDispatchSetSecurity(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-    PQUEUE_ENTRY Entry;
+    PKSOBJECT_CREATE_ITEM CreateItem;
+    PIO_STACK_LOCATION IoStack;
+    PGENERIC_MAPPING Mapping;
+    PSECURITY_DESCRIPTOR Descriptor;
+    NTSTATUS Status;
 
-    if (!QueueHead || !SpinLock || !Irp)
-        return;
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    Entry = ExAllocatePool(NonPagedPool, sizeof(QUEUE_ENTRY));
-    if (!Entry)
-        return;
+    /* get create item */
+    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 
-    ///FIXME
-    // setup cancel routine
-    //
+    if (!CreateItem || !CreateItem->SecurityDescriptor)
+    {
+        /* no create item */
+        Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_NO_SECURITY_ON_OBJECT;
+    }
 
-    Entry->Irp = Irp;
+    /* backup old descriptor */
+    Descriptor = CreateItem->SecurityDescriptor;
 
-    if (ListLocation == KsListEntryTail)
-        ExInterlockedInsertTailList(QueueHead, &Entry->Entry, SpinLock);
-    else
-        ExInterlockedInsertHeadList(QueueHead, &Entry->Entry, SpinLock);
+    /* 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 */
+        ExFreePool(Descriptor);
+
+       /* mark create item as changed */
+       CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED;
+    }
+
+    /* store result */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+    return Status;
 }
 
 /*
     @unimplemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsAddObjectCreateItemToObjectHeader(
-    IN  KSOBJECT_HEADER Header,
-    IN  PDRIVER_DISPATCH Create,
-    IN  PVOID Context,
-    IN  PWCHAR ObjectClass,
-    IN  PSECURITY_DESCRIPTOR SecurityDescriptor)
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsDispatchSpecificMethod(
+    IN  PIRP Irp,
+    IN  PFNKSHANDLER Handler)
 {
     UNIMPLEMENTED;
     return STATUS_UNSUCCESSFUL;
@@ -74,73 +135,98 @@ KsAddObjectCreateItemToObjectHeader(
 KSDDKAPI
 NTSTATUS
 NTAPI
-KsAddObjectCreateItemToDeviceHeader(
-    IN  KSDEVICE_HEADER DevHeader,
-    IN  PDRIVER_DISPATCH Create,
-    IN  PVOID Context,
-    IN  PWCHAR ObjectClass,
-    IN  PSECURITY_DESCRIPTOR SecurityDescriptor)
+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)
 {
-    PKSIDEVICE_HEADER Header;
-    ULONG FreeIndex, Index;
-
-    Header = (PKSIDEVICE_HEADER)DevHeader;
+    PDEVICE_OBJECT DeviceObject;
+    PIRP Irp;
+    NTSTATUS Status;
+    BOOLEAN Result;
+    KEVENT LocalEvent;
 
-    DPRINT1("KsAddObjectCreateItemToDeviceHeader entered\n");
+    if (Event)
+    {
+        /* make sure event is reset */
+        KeClearEvent(Event);
+    }
 
-     /* check if a device header has been provided */
-    if (!DevHeader)
-        return STATUS_INVALID_PARAMETER_1;
+    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;
 
-    /* check if a create item has been provided */
-    if (!Create)
-        return STATUS_INVALID_PARAMETER_2;
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("Invalid user buffer provided\n");
+             return Status;
+         }
+    }
 
-    /* check if a object class has been provided */
-    if (!ObjectClass)
-        return STATUS_INVALID_PARAMETER_4;
+    /* get corresponding device object */
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    FreeIndex = (ULONG)-1;
-    /* now scan the list and check for a free item */
-    for(Index = 0; Index < Header->MaxItems; Index++)
+    /* fast-io read is only available for kernel mode clients */
+    if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
+        DeviceObject->DriverObject->FastIoDispatch->FastIoRead)
     {
-        if (!Header->ItemList[Index].bCreated)
-        {
-            if (FreeIndex == (ULONG)-1)
-                FreeIndex = Index;
+        /* call fast io write */
+        Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
 
-            continue;
-        }
-        else if (!wcsicmp(ObjectClass, Header->ItemList[Index].CreateItem.ObjectClass.Buffer))
+        if (Result && NT_SUCCESS(IoStatusBlock->Status))
         {
-            /* the same object class already exists */
-            return STATUS_OBJECT_NAME_COLLISION;
+            /* request was handeled and succeeded */
+            return STATUS_SUCCESS;
         }
     }
-    /* found a free index */
-    if (FreeIndex == (ULONG)-1)
+
+    /* do the slow way */
+    if (!Event)
     {
-        /* allocate a new device entry */
-        PDEVICE_ITEM Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_ITEM) * (Header->MaxItems + 1), TAG_DEVICE_HEADER);
-        if (!Item)
-            return STATUS_INSUFFICIENT_RESOURCES;
+        /* initialize temp event */
+        KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
+        Event = &LocalEvent;
+    }
 
-        RtlMoveMemory(Item, Header->ItemList, Header->MaxItems * sizeof(DEVICE_ITEM));
-        ExFreePoolWithTag(Header->ItemList, TAG_DEVICE_HEADER);
-        
-        Header->ItemList = Item;
-        FreeIndex = Header->MaxItems;
-        Header->MaxItems++;
-    }
-
-    /* store the new item */
-    Header->ItemList[FreeIndex].bCreated = TRUE;
-    Header->ItemList[FreeIndex].CreateItem.Create = Create;
-    Header->ItemList[FreeIndex].CreateItem.Context = Context;
-    RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem.ObjectClass, ObjectClass);
-    Header->ItemList[FreeIndex].CreateItem.SecurityDescriptor = SecurityDescriptor;
-    Header->ItemList[FreeIndex].CreateItem.Flags = 0;
-    return STATUS_SUCCESS;
+    /* 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;
 }
 
 /*
@@ -149,486 +235,1113 @@ KsAddObjectCreateItemToDeviceHeader(
 KSDDKAPI
 NTSTATUS
 NTAPI
-KsAllocateDeviceHeader(
-    OUT KSDEVICE_HEADER* OutHeader,
-    IN  ULONG ItemsCount,
-    IN  PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
+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)
 {
-    ULONG Index = 0;
-    PKSIDEVICE_HEADER Header;
-
-    if (!OutHeader)
-        return STATUS_INVALID_PARAMETER;
+    PDEVICE_OBJECT DeviceObject;
+    PIRP Irp;
+    NTSTATUS Status;
+    BOOLEAN Result;
+    KEVENT LocalEvent;
 
-    /* allocate a device header */
-    Header = ExAllocatePoolWithTag(PagedPool, sizeof(KSIDEVICE_HEADER), TAG_DEVICE_HEADER);
+    if (Event)
+    {
+        /* make sure event is reset */
+        KeClearEvent(Event);
+    }
 
-    /* check for success */
-    if (!Header)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    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;
 
-    /* clear all memory */
-    RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("Invalid user buffer provided\n");
+             return Status;
+         }
+    }
 
-    /* initialize spin lock */
-    KeInitializeSpinLock(&Header->ItemListLock);
+    /* get corresponding device object */
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    /* are there any create items provided */
-    if (ItemsCount && ItemsList)
+    /* fast-io write is only available for kernel mode clients */
+    if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
+        DeviceObject->DriverObject->FastIoDispatch->FastIoWrite)
     {
-        /* allocate space for device item list */
-        Header->ItemList = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_ITEM) * ItemsCount, TAG_DEVICE_HEADER);
-        if (!Header->ItemList)
-        {
-            ExFreePoolWithTag(Header, TAG_DEVICE_HEADER);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-        RtlZeroMemory(Header->ItemList, sizeof(DEVICE_ITEM) * ItemsCount);
+        /* call fast io write */
+        Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
 
-        for(Index = 0; Index < ItemsCount; Index++)
+        if (Result && NT_SUCCESS(IoStatusBlock->Status))
         {
-            /* copy provided create items */
-            RtlMoveMemory(&Header->ItemList[Index].CreateItem, &ItemsList[Index], sizeof(KSOBJECT_CREATE_ITEM));
-            if (ItemsList[Index].Create!= NULL)
-            {
-                Header->ItemList[Index].bCreated = TRUE;
-            }
+            /* request was handeled and succeeded */
+            return STATUS_SUCCESS;
         }
-        Header->MaxItems = ItemsCount;
     }
 
-    /* store result */
-    *OutHeader = Header;
+    /* do the slow way */
+    if (!Event)
+    {
+        /* initialize temp event */
+        KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
+        Event = &LocalEvent;
+    }
 
-    return STATUS_SUCCESS;
+    /* 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;
 }
 
 /*
-    @unimplemented
-
-    http://www.osronline.com/DDKx/stream/ksfunc_3sc3.htm
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
 NTAPI
-KsAllocateObjectCreateItem(
-    IN  KSDEVICE_HEADER DevHeader,
-    IN  PKSOBJECT_CREATE_ITEM CreateItem,
-    IN  BOOLEAN AllocateEntry,
-    IN  PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
+KsQueryInformationFile(
+    IN  PFILE_OBJECT FileObject,
+    OUT PVOID FileInformation,
+    IN  ULONG Length,
+    IN  FILE_INFORMATION_CLASS FileInformationClass)
 {
-    PKSIDEVICE_HEADER Header;
+    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;
 
-    Header = (PKSIDEVICE_HEADER)DevHeader;
+    /* get related file object */
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    if (!DevHeader)
-        return STATUS_INVALID_PARAMETER_1;
+    /* get fast i/o table */
+    FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
 
-    if (!CreateItem)
-        return STATUS_INVALID_PARAMETER_2;
+    /* 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);
 
-    //FIXME
-    //handle ItemFreeCallback
-    //
-    if (AllocateEntry && ItemFreeCallback)
-        DPRINT1("Ignoring ItemFreeCallback\n");
+    /* initialize event */
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
 
-    return KsAddObjectCreateItemToDeviceHeader(DevHeader, CreateItem->Create, CreateItem->Context, CreateItem->ObjectClass.Buffer, CreateItem->SecurityDescriptor);
-}
+    /* set offset to zero */
+    Offset.QuadPart = 0L;
 
+    /* build the request */
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &StatusBlock);
 
-/*
-    @implemented
-*/
-KSDDKAPI
-VOID
-NTAPI
-KsFreeDeviceHeader(
-    IN  KSDEVICE_HEADER DevHeader)
-{
-    PKSIDEVICE_HEADER Header;
+    if (!Irp)
+        return STATUS_INSUFFICIENT_RESOURCES;
 
-    Header = (PKSIDEVICE_HEADER)DevHeader;
+    /* get next stack location */
+    IoStack = IoGetNextIrpStackLocation(Irp);
 
-    if (!DevHeader)
-        return;
+    /* setup parameters */
+    IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
+    IoStack->Parameters.QueryFile.Length = Length;
+    Irp->AssociatedIrp.SystemBuffer = FileInformation;
 
-    ExFreePoolWithTag(Header->ItemList, TAG_DEVICE_HEADER);
-    ExFreePoolWithTag(Header, TAG_DEVICE_HEADER);
-}
 
-/*
-    @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsAllocateExtraData(
-    IN  PIRP Irp,
-    IN  ULONG ExtraSize,
-    OUT PVOID* ExtraBuffer)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
-}
+    /* call the driver */
+    Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
 
-/*
-    @unimplemented
+    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;
+    }
 
-    Initialize the required file context header.
-    Allocates KSOBJECT_HEADER structure.
-    Irp is an IRP_MJ_CREATE structure.
-    Driver must allocate KSDISPATCH_TABLE and initialize it first.
+    /* done */
+    return Status;
+}
 
-    http://www.osronline.com/DDKx/stream/ksfunc_0u2b.htm
+/*
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
 NTAPI
-KsAllocateObjectHeader(
-    OUT KSOBJECT_HEADER *Header,
-    IN  ULONG ItemsCount,
-    IN  PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,
-    IN  PIRP Irp,
-    IN  KSDISPATCH_TABLE* Table)
+KsSetInformationFile(
+    IN  PFILE_OBJECT FileObject,
+    IN  PVOID FileInformation,
+    IN  ULONG Length,
+    IN  FILE_INFORMATION_CLASS FileInformationClass)
 {
     PIO_STACK_LOCATION IoStack;
-    PDEVICE_EXTENSION DeviceExtension;
-    PKSIDEVICE_HEADER DeviceHeader;
-    PKSIOBJECT_HEADER ObjectHeader;
-    WCHAR ObjectClass[50];
-
-    if (!Header)
-        return STATUS_INVALID_PARAMETER_1;
-
-    if (!Irp)
-        return STATUS_INVALID_PARAMETER_4;
-
-    if (!Table)
-        return STATUS_INVALID_PARAMETER_5;
+    PDEVICE_OBJECT DeviceObject;
+    PIRP Irp;
+    PVOID Buffer;
+    KEVENT Event;
+    LARGE_INTEGER Offset;
+    IO_STATUS_BLOCK IoStatus;
+    NTSTATUS Status;
 
-    /* get current stack location */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
-    /* get device extension */
-    DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
-    /* get device header */
-    DeviceHeader = DeviceExtension->DeviceHeader;
+    /* get related device object */
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    ObjectClass[0] = L'\0';
-    /* check for an file object */
-    if (IoStack->FileObject != NULL)
-    {
-        /* validate the file name */
-        if (IoStack->FileObject->FileName.Length >= 38)
-        {
-            RtlMoveMemory(ObjectClass, IoStack->FileObject->FileName.Buffer, 38 * sizeof(WCHAR));
-            ObjectClass[38] = L'\0';
-            DPRINT1("ObjectClass %S\n", ObjectClass);
-        }
-    }
-    /* allocate the object header */
-    ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
-    if (!ObjectHeader)
+    /* copy file information */
+    Buffer = AllocateItem(NonPagedPool, Length);
+    if (!Buffer)
         return STATUS_INSUFFICIENT_RESOURCES;
 
-    /* initialize object header */
-    RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
-
-    /* do we have a name */
-    if (ObjectClass[0])
+    _SEH2_TRY
     {
-        ObjectHeader->ObjectClass = ExAllocatePoolWithTag(NonPagedPool, 40 * sizeof(WCHAR), TAG_DEVICE_HEADER);
-        if (ObjectHeader->ObjectClass)
-        {
-            wcscpy(ObjectHeader->ObjectClass, ObjectClass);
-        }
+        ProbeForRead(Buffer, Length, sizeof(UCHAR));
+        RtlMoveMemory(Buffer, FileInformation, Length);
+        Status = STATUS_SUCCESS;
     }
-
-    /* copy dispatch table */
-    RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
-    /* store create items */
-    if (ItemsCount && ItemsList)
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        ObjectHeader->ItemCount = ItemsCount;
-        ObjectHeader->CreateItem = ItemsList;
+        /* Exception, get the error code */
+        Status = _SEH2_GetExceptionCode();
     }
+    _SEH2_END;
 
-    /* was the request for a pin/clock/node */
-    if (IoStack->FileObject)
+    if (!NT_SUCCESS(Status))
     {
-        /* store the object in the file object */
-        ASSERT(IoStack->FileObject->FsContext == NULL);
-        IoStack->FileObject->FsContext = ObjectHeader;
+        /* invalid user buffer */
+        FreeItem(Buffer);
+        return Status;
     }
-    else
+
+    /* 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)
     {
-        /* the object header is for device */
-        ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
-        DeviceHeader->ItemList[DeviceHeader->DeviceIndex].ObjectHeader = ObjectHeader;
+        /* failed to allocate irp */
+        FreeItem(Buffer);
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    /* store result */
-    *Header = ObjectHeader;
-
+    /* get next stack location */
+    IoStack = IoGetNextIrpStackLocation(Irp);
 
-    DPRINT1("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectClass, IoStack->FileObject, ObjectHeader);
+    /* 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;
 
-    return STATUS_SUCCESS;
+    /* 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;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
-VOID
+NTSTATUS
 NTAPI
-KsFreeObjectHeader(
-    IN  PVOID Header)
+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);
+    }
 
-/*
-    @unimplemented
-*/
-KSDDKAPI VOID NTAPI
-KsCancelIo(
-    IN  OUT PLIST_ENTRY QueueHead,
-    IN  PKSPIN_LOCK SpinLock)
-{
-    UNIMPLEMENTED;
-}
+    if (RequestorMode || ExGetPreviousMode() == KernelMode)
+    {
+        /* requestor is from kernel land */
+        ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
 
-/*
-    @unimplemented
-*/
-KSDDKAPI VOID NTAPI
-KsCancelRoutine(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    UNIMPLEMENTED;
-}
+        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;
+                    }
+                }
+            }
+        }
+    }
 
-/*
-    @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsDefaultDeviceIoCompletion(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
-}
+    /* clear file object event */
+    KeClearEvent(&FileObject->Event);
 
-/*
-    @unimplemented
-*/
-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)   /* always return false */
-{
-    return FALSE;
-}
+    /* set the offset to zero */
+    Offset.QuadPart = 0LL;
 
-/*
-    @unimplemented
-*/
-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)   /* always return false */
-{
-    return FALSE;
-}
+    /* 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;
+    }
 
-/*
-    Used in dispatch table entries that aren't handled and need to return
-    STATUS_INVALID_DEVICE_REQUEST.
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsDispatchInvalidDeviceRequest(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    /* setup irp parameters */
+    Irp->RequestorMode = RequestorMode;
+    Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
+    Irp->Tail.Overlay.OriginalFileObject = FileObject;
+    Irp->UserBuffer = StreamHeaders;
 
-    return STATUS_INVALID_DEVICE_REQUEST;
-}
+    /* 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);
 
-/*
-    @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsDispatchSpecificMethod(
-    IN  PIRP Irp,
-    IN  PFNKSHANDLER Handler)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
-}
+    if (CompletionRoutine)
+    {
+        /* setup completion routine for async processing */
+        IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
+    }
 
-/*
-    @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsDispatchSpecificProperty(
-    IN  PIRP Irp,
-    IN  PFNKSHANDLER Handler)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    /* now call the driver */
+    Status = IoCallDriver(DeviceObject, Irp);
+    /* done */
+    return Status;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsForwardAndCatchIrp(
-    IN  PDEVICE_OBJECT DeviceObject,
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsProbeStreamIrp(
     IN  PIRP Irp,
-    IN  PFILE_OBJECT FileObject,
-    IN  KSSTACK_USE StackUse)
+    IN  ULONG ProbeFlags,
+    IN  ULONG HeaderSize)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
-}
+    PMDL Mdl;
+    PVOID Buffer;
+    LOCK_OPERATION Operation;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PKSSTREAM_HEADER StreamHeader;
+    PIO_STACK_LOCATION IoStack;
+    ULONG Length;
+    BOOLEAN AllocateMdl = FALSE;
 
-/*
-    @unimplemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsForwardIrp(
-    IN  PIRP Irp,
-    IN  PFILE_OBJECT FileObject,
-    IN  BOOLEAN ReuseStackLocation)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+    if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer)
+    {
+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 */
+                        Operation = (ProbeFlags & KSPROBE_STREAMWRITE) ? IoWriteAccess : 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 */
+                    Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, Irp->MdlAddress != NULL, 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;
+    }
+
+#if 0
+    // HACK for MS PORTCLS
+       HeaderSize = Length;
+#endif
+    /* probe user mode buffers */
+    if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
+    {
+        /* allocate stream header buffer */
+        Irp->AssociatedIrp.SystemBuffer = ExAllocatePool(NonPagedPool, Length);
+
+        if (!Irp->AssociatedIrp.SystemBuffer)
+        {
+            /* no memory */
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        _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));
+            }
+
+            /* 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;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsGetChildCreateParameter(
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsAllocateExtraData(
     IN  PIRP Irp,
-    OUT PVOID* CreateParameter)
+    IN  ULONG ExtraSize,
+    OUT PVOID* ExtraBuffer)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    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;
 }
 
 /*
-    @unimplemented
+    @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)
+KSDDKAPI
+VOID
+NTAPI
+KsNullDriverUnload(
+    IN  PDRIVER_OBJECT DriverObject)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsProbeStreamIrp(
-    IN  PIRP Irp,
-    IN  ULONG ProbeFlags,
-    IN  ULONG HeaderSize)
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsDispatchInvalidDeviceRequest(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_INVALID_DEVICE_REQUEST;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsQueryInformationFile(
-    IN  PFILE_OBJECT FileObject,
-    OUT PVOID FileInformation,
-    IN  ULONG Length,
-    IN  FILE_INFORMATION_CLASS FileInformationClass)
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsDefaultDeviceIoCompletion(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    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;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+
+    return Status;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI ACCESS_MASK NTAPI
-KsQueryObjectAccessMask(
-    IN KSOBJECT_HEADER Header)
+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)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return FALSE;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI PKSOBJECT_CREATE_ITEM NTAPI
-KsQueryObjectCreateItem(
-    IN KSOBJECT_HEADER Header)
+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)
 {
-    UNIMPLEMENTED;
-/*    return STATUS_UNSUCCESSFUL; */
-    return NULL;
+    return FALSE;
 }
 
+
 /*
-    @unimplemented
+    @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)
+KSDDKAPI
+VOID
+NTAPI
+KsCancelIo(
+    IN  OUT PLIST_ENTRY QueueHead,
+    IN  PKSPIN_LOCK SpinLock)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    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);
+
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI VOID NTAPI
+KSDDKAPI
+VOID
+NTAPI
 KsReleaseIrpOnCancelableQueue(
     IN  PIRP Irp,
     IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
 {
-    UNIMPLEMENTED;
+    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);
+    }
 }
 
 /*
@@ -643,360 +1356,600 @@ KsRemoveIrpFromCancelableQueue(
     IN  KSLIST_ENTRY_LOCATION ListLocation,
     IN  KSIRP_REMOVAL_OPERATION RemovalOperation)
 {
-    PQUEUE_ENTRY Entry = NULL;
     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;
 
-    if (RemovalOperation != KsAcquireOnly && RemovalOperation != KsAcquireAndRemove)
-        return NULL;
-
+    /* acquire list lock */
     KeAcquireSpinLock(SpinLock, &OldIrql);
 
-    if (!IsListEmpty(QueueHead))
+    /* point to queue head */
+    CurEntry = QueueHead;
+
+    do
     {
-        if (RemovalOperation == KsAcquireOnly)
+        /* 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)
         {
-            if (ListLocation == KsListEntryHead)
-                Entry = (PQUEUE_ENTRY)QueueHead->Flink;
-            else
-                Entry = (PQUEUE_ENTRY)QueueHead->Blink;
+            /* reached end of list */
+            break;
         }
-        else if (RemovalOperation == KsAcquireAndRemove)
+
+        /* get irp offset */
+        Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
+
+        if (Irp->Cancel)
         {
-            if (ListLocation == KsListEntryTail)
-                Entry = (PQUEUE_ENTRY)RemoveTailList(QueueHead);
-            else
-                Entry = (PQUEUE_ENTRY)RemoveHeadList(QueueHead);
+            /* 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 (!Entry)
-        return NULL;
+    if (!Irp || Irp->CancelRoutine == NULL)
+    {
+        /* either an irp has been acquired or nothing found */
+        return Irp;
+    }
 
-    Irp = Entry->Irp;
+    /* time to remove the canceled irp */
+    IoAcquireCancelSpinLock(&OldIrql);
+    /* acquire list lock */
+    KeAcquireSpinLockAtDpcLevel(SpinLock);
 
-    if (RemovalOperation == KsAcquireAndRemove)
-        ExFreePool(Entry);
+    if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
+    {
+        /* remove it */
+        RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+    }
 
-    return Irp;
-}
+    /* release list lock */
+    KeReleaseSpinLockFromDpcLevel(SpinLock);
 
-/*
-    @unimplemented
-*/
-KSDDKAPI VOID NTAPI
-KsRemoveSpecificIrpFromCancelableQueue(
-    IN  PIRP Irp)
-{
-    UNIMPLEMENTED;
+    /* release cancel spinlock */
+    IoReleaseCancelSpinLock(OldIrql);
+    /* no non canceled irp has been found */
+    return NULL;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsSetInformationFile(
-    IN  PFILE_OBJECT FileObject,
-    IN  PVOID FileInformation,
-    IN  ULONG Length,
-    IN  FILE_INFORMATION_CLASS FileInformationClass)
+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)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
-}
+    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);
 
-NTAPI
-NTSTATUS
-KsCreate(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    //PIO_STACK_LOCATION IoStack;
-    PDEVICE_EXTENSION DeviceExtension;
-    PKSIDEVICE_HEADER DeviceHeader;
-    ULONG Index;
-    NTSTATUS Status = STATUS_SUCCESS;
-    KIRQL OldLevel;
+        /* now acquire destination lock */
+        KeAcquireSpinLockAtDpcLevel(DestinationLock);
+    }
 
-    DPRINT1("KS / CREATE\n");
-    /* get current stack location */
-    //IoStack = IoGetCurrentIrpStackLocation(Irp);
-    /* get device extension */
-    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
-    /* get device header */
-    DeviceHeader = DeviceExtension->DeviceHeader;
+    /* point to list head */
+    SrcEntry = SourceList;
 
-    /* acquire list lock */
-    KeAcquireSpinLock(&DeviceHeader->ItemListLock, &OldLevel);
-    /* loop all device items */
-    for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
+    /* now move all irps */
+    while(TRUE)
     {
-        if (DeviceHeader->ItemList[Index].bCreated && DeviceHeader->ItemList[Index].ObjectHeader == NULL)
+        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
         {
-            DeviceHeader->DeviceIndex = Index;
-             /* set object create item */
-            KSCREATE_ITEM_IRP_STORAGE(Irp) = &DeviceHeader->ItemList[Index].CreateItem;
-            Status = DeviceHeader->ItemList[Index].CreateItem.Create(DeviceObject, Irp);
+            if (Status != STATUS_NO_MATCH)
+            {
+                /* callback decided to stop enumeration */
+                break;
+            }
+
+            /* reset return value */
+            Status = STATUS_SUCCESS;
         }
     }
 
-    /* release lock */
-    KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
+    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;
 }
 
-static NTAPI
-NTSTATUS
-KsClose(
-    IN  PDEVICE_OBJECT DeviceObject,
+/*
+    @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;
-    PKSIOBJECT_HEADER ObjectHeader;
+    KIRQL OldLevel;
 
-    /* get current stack location */
+    DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
+    /* check for required parameters */
+    if (!QueueHead || !SpinLock || !Irp)
+        return;
+
+    if (!DriverCancel)
+    {
+        /* default to KsCancelRoutine */
+        DriverCancel = KsCancelRoutine;
+    }
+
+    /* get current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    DPRINT1("KS / CLOSE\n");
+    /* acquire spinlock */
+    KeAcquireSpinLock(SpinLock, &OldLevel);
 
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
+    if (ListLocation == KsListEntryTail)
     {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
-
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.Close(DeviceObject, Irp);
+        /* insert irp to tail of list */
+        InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
     }
     else
     {
-        DPRINT1("Expected Object Header\n");
-        return STATUS_SUCCESS;
+        /* insert irp to head of list */
+        InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
     }
-}
 
-static NTAPI
-NTSTATUS
-KsDeviceControl(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    PIO_STACK_LOCATION IoStack;
-    PKSIOBJECT_HEADER ObjectHeader;
+    /* store internal queue lock */
+    KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
 
-    /* get current stack location */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    /* now set the cancel routine */
+    OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
 
-    DPRINT1("KS / DeviceControl\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
+    if (Irp->Cancel && OldDriverCancel == NULL)
     {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+        /* the irp has already been canceled */
+        KeReleaseSpinLock(SpinLock, OldLevel);
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
+        /* cancel routine requires that cancel spinlock is held */
+        IoAcquireCancelSpinLock(&Irp->CancelIrql);
+
+        /* cancel irp */
+        DriverCancel(IoStack->DeviceObject, Irp);
     }
     else
     {
-        DPRINT1("Expected Object Header\n");
-        KeBugCheckEx(0, 0, 0, 0, 0);
-        return STATUS_SUCCESS;
+        /* done */
+        KeReleaseSpinLock(SpinLock, OldLevel);
     }
 }
 
-static NTAPI
-NTSTATUS
-KsRead(
+/*
+    @implemented
+*/
+KSDDKAPI
+VOID
+NTAPI
+KsCancelRoutine(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  PIRP Irp)
 {
-    PIO_STACK_LOCATION IoStack;
-    PKSIOBJECT_HEADER ObjectHeader;
+    PKSPIN_LOCK SpinLock;
 
-    /* get current stack location */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    /* get internal queue lock */
+    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
 
-    DPRINT1("KS / Read\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
-    {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+    /* acquire spinlock */
+    KeAcquireSpinLockAtDpcLevel(SpinLock);
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.Read(DeviceObject, Irp);
-    }
-    else
+    /* 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)
     {
-        DPRINT1("Expected Object Header\n");
-        KeBugCheckEx(0, 0, 0, 0, 0);
-        return STATUS_SUCCESS;
+        /* let's complete it */
+        Irp->IoStatus.Status = STATUS_CANCELLED;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 }
 
-static NTAPI
 NTSTATUS
-KsWrite(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
+FindMatchingCreateItem(
+    PLIST_ENTRY ListHead,
+    ULONG BufferSize,
+    LPWSTR Buffer,
+    OUT PCREATE_ITEM_ENTRY *OutCreateItem)
 {
-    PIO_STACK_LOCATION IoStack;
-    PKSIOBJECT_HEADER ObjectHeader;
+    PLIST_ENTRY Entry;
+    PCREATE_ITEM_ENTRY CreateItemEntry;
+    UNICODE_STRING RefString;
 
-    /* get current stack location */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    DPRINT1("KS / Write\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
-    {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+#ifndef MS_KSUSER
+    /* remove '\' slash */
+    Buffer++;
+    BufferSize -= sizeof(WCHAR);
+#endif
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.Write(DeviceObject, Irp);
+    if (!wcschr(Buffer, L'\\'))
+    {
+        RtlInitUnicodeString(&RefString, Buffer);
     }
     else
     {
-        DPRINT1("Expected Object Header %p\n", IoStack->FileObject);
-        KeBugCheckEx(0, 0, 0, 0, 0);
-        return STATUS_SUCCESS;
+        RefString.Buffer = Buffer;
+        RefString.Length = RefString.MaximumLength = ((ULONG_PTR)wcschr(Buffer, L'\\') - (ULONG_PTR)Buffer);
     }
-}
-
-static NTAPI
-NTSTATUS
-KsFlushBuffers(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
-{
-    PIO_STACK_LOCATION IoStack;
-    PKSIOBJECT_HEADER ObjectHeader;
 
-    /* get current stack location */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    /* point to first entry */
+    Entry = ListHead->Flink;
 
-    DPRINT1("KS / FlushBuffers\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
+    /* loop all device items */
+    while(Entry != ListHead)
     {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+        /* get create item entry */
+        CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.Flush(DeviceObject, Irp);
-    }
-    else
-    {
-        DPRINT1("Expected Object Header\n");
-        KeBugCheckEx(0, 0, 0, 0, 0);
-        return STATUS_SUCCESS;
+        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;
+        }
+
+        ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
+
+        DPRINT("CreateItem %S Length %u Request %wZ %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
+                                                           CreateItemEntry->CreateItem->ObjectClass.Length,
+                                                           &RefString,
+                                                           BufferSize);
+
+        if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
+        {
+            /* 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;
 }
 
-static NTAPI
 NTSTATUS
-KsQuerySecurity(
+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);
+        return STATUS_SUCCESS;
+    }
 
-    DPRINT1("KS / QuerySecurity\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
+    if (IoStack->FileObject->RelatedFileObject != NULL)
     {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+        /* request is to instantiate a pin / node / clock / allocator */
+        ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
+
+        /* sanity check */
+        ASSERT(ObjectHeader);
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.QuerySecurity(DeviceObject, Irp);
+        /* find a matching a create item */
+        Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
     }
     else
     {
-        DPRINT1("Expected Object Header\n");
-        KeBugCheckEx(0, 0, 0, 0, 0);
-        return STATUS_SUCCESS;
+        /* 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);
+    return STATUS_UNSUCCESSFUL;
 }
 
-static NTAPI
 NTSTATUS
-KsSetSecurity(
+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);
 
-    DPRINT1("KS / SetSecurity\n");
-    if (IoStack->FileObject && IoStack->FileObject->FsContext)
-    {
-        ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
+    /* get device extension */
+    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    /* get device header */
+    DeviceHeader = DeviceExtension->DeviceHeader;
 
-        KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
-        return ObjectHeader->DispatchTable.SetSecurity(DeviceObject, Irp);
-    }
-    else
+    ASSERT(IoStack->FileObject);
+
+    /* get object header */
+    ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2;
+
+    if (!ObjectHeader)
     {
-        DPRINT1("Expected Object Header\n");
-        KeBugCheckEx(0, 0, 0, 0, 0);
+        /* FIXME Pnp-Issue*/
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = 0;
+        /* complete and forget */
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_SUCCESS;
     }
-}
-
-/*
-    @implemented
-*/
-KSDDKAPI NTSTATUS NTAPI
-KsSetMajorFunctionHandler(
-    IN  PDRIVER_OBJECT DriverObject,
-    IN  ULONG MajorFunction)
-{
-    /*
-        Sets a DriverObject's major function handler to point to an internal
-        function we implement.
 
-        TODO: Deal with KSDISPATCH_FASTIO
-    */
+    /* sanity check */
+    ASSERT(ObjectHeader);
+    /* store create item */
+    //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
 
-    switch ( MajorFunction )
+    /* retrieve matching dispatch function */
+    switch(IoStack->MajorFunction)
     {
-        case IRP_MJ_CREATE:
-            DriverObject->MajorFunction[MajorFunction] = KsCreate;
-            break;
         case IRP_MJ_CLOSE:
-            DriverObject->MajorFunction[MajorFunction] = KsClose;
+            Dispatch = ObjectHeader->DispatchTable.Close;
             break;
         case IRP_MJ_DEVICE_CONTROL:
-            DriverObject->MajorFunction[MajorFunction] = KsDeviceControl;
+            Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
             break;
         case IRP_MJ_READ:
-            DriverObject->MajorFunction[MajorFunction] = KsRead;
+            Dispatch = ObjectHeader->DispatchTable.Read;
             break;
         case IRP_MJ_WRITE:
-            DriverObject->MajorFunction[MajorFunction] = KsWrite;
+            Dispatch = ObjectHeader->DispatchTable.Write;
             break;
         case IRP_MJ_FLUSH_BUFFERS :
-            DriverObject->MajorFunction[MajorFunction] = KsFlushBuffers;
+            Dispatch = ObjectHeader->DispatchTable.Flush;
             break;
         case IRP_MJ_QUERY_SECURITY:
-            DriverObject->MajorFunction[MajorFunction] = KsQuerySecurity;
+            Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
             break;
         case IRP_MJ_SET_SECURITY:
-            DriverObject->MajorFunction[MajorFunction] = KsSetSecurity;
+            Dispatch = ObjectHeader->DispatchTable.SetSecurity;
             break;
-
+        case IRP_MJ_PNP:
+            Dispatch = KsDefaultDispatchPnp;
         default:
-            return STATUS_INVALID_PARAMETER;    /* is this right? */
-    };
+            Dispatch = NULL;
+    }
 
-    return STATUS_SUCCESS;
+    /* 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;
 }
 
 /*
@@ -1005,52 +1958,39 @@ KsSetMajorFunctionHandler(
 KSDDKAPI
 NTSTATUS
 NTAPI
-KsDispatchIrp(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp)
+KsSetMajorFunctionHandler(
+    IN  PDRIVER_OBJECT DriverObject,
+    IN  ULONG MajorFunction)
 {
-    PIO_STACK_LOCATION IoStack;
-
-    /* Calls a dispatch routine corresponding to the function code of the IRP */
-    /*
-        First we need to get the dispatch table. An opaque header is pointed to by
-        FsContext. The first element points to this table. This table is the key
-        to dispatching the IRP correctly.
-    */
-
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DPRINT1("KsDispatchIrp %x\n", IoStack->MajorFunction);
+    DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
+#if 1
+    // HACK
+    // for MS PORTCLS
+    //
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate;
+#endif
 
-    switch (IoStack->MajorFunction)
+    switch ( MajorFunction )
     {
         case IRP_MJ_CREATE:
-            return KsCreate(DeviceObject, Irp);
-        case IRP_MJ_CLOSE:
-            return KsClose(DeviceObject, Irp);
+            DriverObject->MajorFunction[MajorFunction] = KspCreate;
             break;
         case IRP_MJ_DEVICE_CONTROL:
-            return KsDeviceControl(DeviceObject, Irp);
-            break;
+        case IRP_MJ_CLOSE:
         case IRP_MJ_READ:
-            return KsRead(DeviceObject, Irp);
-            break;
         case IRP_MJ_WRITE:
-            return KsWrite(DeviceObject, Irp);
-            break;
-        case IRP_MJ_FLUSH_BUFFERS:
-            return KsFlushBuffers(DeviceObject, Irp);
-            break;
+        case IRP_MJ_FLUSH_BUFFERS :
         case IRP_MJ_QUERY_SECURITY:
-            return KsQuerySecurity(DeviceObject, Irp);
-            break;
         case IRP_MJ_SET_SECURITY:
-            return KsSetSecurity(DeviceObject, Irp);
+            DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
             break;
         default:
-            return STATUS_INVALID_PARAMETER;    /* is this right? */
+            DPRINT1("NotSupported %x\n", MajorFunction);
+            return STATUS_INVALID_PARAMETER;
     };
-}
 
+    return STATUS_SUCCESS;
+}
 
 /*
     @implemented
@@ -1058,94 +1998,109 @@ KsDispatchIrp(
 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)
+KsDispatchIrp(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp)
 {
-    PIRP Irp;
     PIO_STACK_LOCATION IoStack;
-    PDEVICE_OBJECT DeviceObject;
-    ULONG Code;
-    NTSTATUS Status;
-    LARGE_INTEGER Offset;
+    PKSIDEVICE_HEADER DeviceHeader;
+    PDEVICE_EXTENSION DeviceExtension;
 
-    if (Flags == KSSTREAM_READ)
-        Code = IRP_MJ_READ;
-    else if (Flags == KSSTREAM_WRITE)
-        Code = IRP_MJ_WRITE;
-    else
-        return STATUS_INVALID_PARAMETER;
+    //DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
 
-    DeviceObject = IoGetRelatedDeviceObject(FileObject);
-    if (!DeviceObject)
-        return STATUS_INVALID_PARAMETER;
+    /* get device extension */
+    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    /* get device header */
+    DeviceHeader = DeviceExtension->DeviceHeader;
 
-    if (Event)
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
     {
-        KeResetEvent(Event);
+        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);
+        }
     }
 
-    Offset.QuadPart = 0LL;
-    Irp = IoBuildSynchronousFsdRequest(Code, DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
-    if (!Irp)
+    /* dispatch power */
+    if (IoStack->MajorFunction == IRP_MJ_POWER)
     {
-        return STATUS_UNSUCCESSFUL;
+        /* 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);
+        }
     }
-
-
-    if (CompletionRoutine)
+    else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
     {
-        IoSetCompletionRoutine(Irp,
-                               CompletionRoutine,
-                               CompletionContext,
-                               (CompletionInvocationFlags & KsInvokeOnSuccess),
-                               (CompletionInvocationFlags & KsInvokeOnError),
-                               (CompletionInvocationFlags & KsInvokeOnCancel));
+        /* 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);
     }
-
-    IoStack = IoGetNextIrpStackLocation(Irp);
-    IoStack->FileObject = FileObject;
-
-    Status = IoCallDriver(DeviceObject, Irp);
-    return Status;
-}
-
-/*
-    @unimplemented
-*/
-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)
-{
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
 }
 
 /*
     @unimplemented
 */
-KSDDKAPI NTSTATUS NTAPI
-KsDefaultForwardIrp(
-    IN PDEVICE_OBJECT DeviceObject,
+KSDDKAPI
+ULONG
+NTAPI
+KsGetNodeIdFromIrp(
     IN PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    UNIMPLEMENTED
+    return KSFILTER_NODE;
 }