[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / allocators.c
index 5530a62..5a4970f 100644 (file)
-/* ===============================================================
-    Allocator Functions
-*/
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/ksfilter/ks/allocators.c
+ * PURPOSE:         KS Allocator functions
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+
+#include "priv.h"
+
+typedef enum
+{
+    ALLOCATOR_NPAGED_LOOKASIDE,
+    ALLOCATOR_PAGED_LOOKASIDE,
+    ALLOCATOR_CUSTOM
+}ALLOCATOR_TYPE;
+
+typedef enum
+{
+    ALLOCATOR_DEVICE_CONTROL,
+    ALLOCATOR_DEVICE_CLOSE,
+    ALLOCATOR_ALLOCATE,
+    ALLOCATOR_FREE
+
+}ALLOC_REQUEST;
+
+typedef PVOID (*PFNKSPAGEDPOOLALLOCATE)(IN PPAGED_LOOKASIDE_LIST  Lookaside);
+typedef PVOID (*PFNKSNPAGEDPOOLALLOCATE)(IN PNPAGED_LOOKASIDE_LIST  Lookaside);
+
+typedef VOID (*PFNKSPAGEDPOOLFREE)(IN PPAGED_LOOKASIDE_LIST  Lookaside, IN PVOID  Entry);
+typedef VOID (*PFNKSNPAGEDPOOLFREE)(IN PNPAGED_LOOKASIDE_LIST  Lookaside, IN PVOID  Entry);
+
+typedef VOID (NTAPI *PFNKSNPAGEDPOOLDELETE)(IN PNPAGED_LOOKASIDE_LIST  Lookaside);
+typedef VOID (NTAPI *PFNKSPAGEDPOOLDELETE)(IN PPAGED_LOOKASIDE_LIST  Lookaside);
+
+typedef struct
+{
+    IKsAllocatorVtbl *lpVtbl;
+    LONG ref;
+    PKSIOBJECT_HEADER Header;
+    ALLOCATOR_TYPE Type;
+
+    KSSTREAMALLOCATOR_STATUS Status;
+
+    union
+    {
+        NPAGED_LOOKASIDE_LIST NPagedList;
+        PAGED_LOOKASIDE_LIST PagedList;
+        PVOID CustomList;
+    }u;
+
+    union
+    {
+         PFNKSDEFAULTALLOCATE DefaultAllocate;
+         PFNKSPAGEDPOOLALLOCATE PagedPool;
+         PFNKSNPAGEDPOOLALLOCATE NPagedPool;
+    }Allocate;
+
+   union
+    {
+         PFNKSDEFAULTFREE DefaultFree;
+         PFNKSPAGEDPOOLFREE PagedPool;
+         PFNKSNPAGEDPOOLFREE NPagedPool;
+    }Free;
+
+    union
+    {
+        PFNKSDELETEALLOCATOR DefaultDelete;
+        PFNKSNPAGEDPOOLDELETE NPagedPool;
+        PFNKSPAGEDPOOLDELETE PagedPool;
+    }Delete;
+
+}ALLOCATOR, *PALLOCATOR;
+
+/* use KSNAME_Allocator for IID_IKsAllocator */
+const GUID IID_IKsAllocator =            {0x642F5D00L, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_StreamAllocator = {0x0cf6e4342, 0xec87, 0x11cf, {0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
+
+
+NTSTATUS
+NTAPI
+IKsAllocator_Allocate(
+    IN PFILE_OBJECT FileObject,
+    PVOID *Frame);
+
+VOID
+NTAPI
+IKsAllocator_FreeFrame(
+    IN PFILE_OBJECT FileObject,
+    PVOID Frame);
+
+
+NTSTATUS
+NTAPI
+IKsAllocator_fnQueryInterface(
+    IKsAllocator * iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
+        IsEqualGUIDAligned(refiid, &IID_IKsAllocator))
+    {
+        *Output = &This->lpVtbl;
+        _InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+ULONG
+NTAPI
+IKsAllocator_fnAddRef(
+    IKsAllocator * iface)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    return InterlockedIncrement(&This->ref);
+}
+
+ULONG
+NTAPI
+IKsAllocator_fnRelease(
+    IKsAllocator * iface)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+NTSTATUS
+NTAPI
+IKsAllocator_fnDeviceIoControl(
+    IKsAllocator *iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+    PIO_STACK_LOCATION IoStack;
+    PKSSTREAMALLOCATOR_FUNCTIONTABLE FunctionTable;
+    PKSSTREAMALLOCATOR_STATUS State;
+    PKSPROPERTY Property;
+
+    /* FIXME locks */
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode  != IOCTL_KS_PROPERTY)
+    {
+        /* only KSPROPERTY requests are supported */
+        UNIMPLEMENTED
+
+        /* complete and forget irps */
+        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return STATUS_NOT_IMPLEMENTED;
+   }
+
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
+    {
+        /* invalid request */
+        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    /* check the request */
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+    if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_StreamAllocator))
+    {
+        if (Property->Id == KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE)
+        {
+            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE))
+            {
+                /* buffer too small */
+                Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+                Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE);
+                /* complete and forget irp */
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_BUFFER_TOO_SMALL;
+            }
+            if (!(Property->Flags & KSPROPERTY_TYPE_GET))
+            {
+                /* only support retrieving the property */
+                Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+                /* complete and forget irp */
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_UNSUCCESSFUL;
+            }
+
+            /* get output buffer */
+            FunctionTable = (PKSSTREAMALLOCATOR_FUNCTIONTABLE)Irp->UserBuffer;
+
+            FunctionTable->AllocateFrame = IKsAllocator_Allocate;
+            FunctionTable->FreeFrame = IKsAllocator_FreeFrame;
+
+            /* save result */
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE);
+            /* complete request */
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+        else if (Property->Id == KSPROPERTY_STREAMALLOCATOR_STATUS)
+        {
+            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSPROPERTY_STREAMALLOCATOR_STATUS))
+            {
+                /* buffer too small */
+                Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+                Irp->IoStatus.Information = sizeof(KSPROPERTY_STREAMALLOCATOR_STATUS);
+                /* complete and forget irp */
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_BUFFER_TOO_SMALL;
+            }
+            if (!(Property->Flags & KSPROPERTY_TYPE_GET))
+            {
+                /* only support retrieving the property */
+                Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+                /* complete and forget irp */
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_UNSUCCESSFUL;
+            }
+
+            /* get output buffer */
+            State = (PKSSTREAMALLOCATOR_STATUS)Irp->UserBuffer;
+
+            /* copy allocator status */
+            RtlMoveMemory(State, &This->Status, sizeof(KSSTREAMALLOCATOR_STATUS));
+
+            /* save result */
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_STATUS);
+
+            /* complete request */
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+    }
+
+    /* unhandled request */
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+IKsAllocator_fnClose(
+    IKsAllocator *iface)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    /* FIXME locks */
+
+    /* now close allocator */
+    if (This->Type == ALLOCATOR_CUSTOM)
+    {
+        This->Delete.DefaultDelete(This->u.CustomList);
+    }
+    else if (This->Type == ALLOCATOR_NPAGED_LOOKASIDE)
+    {
+        This->Delete.NPagedPool(&This->u.NPagedList);
+    }
+    else if (This->Type == ALLOCATOR_PAGED_LOOKASIDE)
+    {
+        This->Delete.PagedPool(&This->u.PagedList);
+    }
+
+    /* free object header */
+    KsFreeObjectHeader(&This->Header);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+IKsAllocator_fnAllocateFrame(
+    IKsAllocator *iface,
+    IN PVOID * OutFrame)
+{
+    PVOID Frame = NULL;
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    /* FIXME locks */
+
+    /* now allocate frame */
+    if (This->Type == ALLOCATOR_CUSTOM)
+    {
+        Frame = This->Allocate.DefaultAllocate(This->u.CustomList);
+    }
+    else if (This->Type == ALLOCATOR_NPAGED_LOOKASIDE)
+    {
+        Frame = This->Allocate.NPagedPool(&This->u.NPagedList);
+    }
+    else if (This->Type == ALLOCATOR_PAGED_LOOKASIDE)
+    {
+        Frame = This->Allocate.PagedPool(&This->u.PagedList);
+    }
+
+    if (Frame)
+    {
+        *OutFrame = Frame;
+        InterlockedIncrement((PLONG)&This->Status.AllocatedFrames);
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+VOID
+NTAPI
+IKsAllocator_fnFreeFrame(
+    IKsAllocator *iface,
+    IN PVOID Frame)
+{
+    PALLOCATOR This = (PALLOCATOR)CONTAINING_RECORD(iface, ALLOCATOR, lpVtbl);
+
+    /* now allocate frame */
+    if (This->Type == ALLOCATOR_CUSTOM)
+    {
+        This->Free.DefaultFree(This->u.CustomList, Frame);
+    }
+    else if (This->Type == ALLOCATOR_NPAGED_LOOKASIDE)
+    {
+        This->Free.NPagedPool(&This->u.NPagedList, Frame);
+    }
+    else if (This->Type == ALLOCATOR_PAGED_LOOKASIDE)
+    {
+        This->Free.PagedPool(&This->u.PagedList, Frame);
+    }
+}
+
+
+static IKsAllocatorVtbl vt_IKsAllocator =
+{
+    IKsAllocator_fnQueryInterface,
+    IKsAllocator_fnAddRef,
+    IKsAllocator_fnRelease,
+    IKsAllocator_fnDeviceIoControl,
+    IKsAllocator_fnClose,
+    IKsAllocator_fnAllocateFrame,
+    IKsAllocator_fnFreeFrame
+};
 
-#include <ntddk.h>
-#include <debug.h>
-#include <ks.h>
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI NTSTATUS NTAPI
 KsCreateAllocator(
@@ -15,35 +367,208 @@ KsCreateAllocator(
     IN  PKSALLOCATOR_FRAMING AllocatorFraming,
     OUT PHANDLE AllocatorHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return KspCreateObjectType(ConnectionHandle,
+                               KSSTRING_Allocator,
+                               (PVOID)AllocatorFraming,
+                               sizeof(KSALLOCATOR_FRAMING),
+                               GENERIC_READ,
+                               AllocatorHandle);
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI NTSTATUS NTAPI
 KsCreateDefaultAllocator(
     IN  PIRP Irp)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return KsCreateDefaultAllocatorEx(Irp, NULL, NULL, NULL, NULL, NULL);
 }
 
 /*
-    @unimplemented
+    @implemented
 */
-KSDDKAPI NTSTATUS NTAPI
+KSDDKAPI
+NTSTATUS
+NTAPI
 KsValidateAllocatorCreateRequest(
     IN  PIRP Irp,
-    OUT PKSALLOCATOR_FRAMING* AllocatorFraming)
+    OUT PKSALLOCATOR_FRAMING* OutAllocatorFraming)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    PKSALLOCATOR_FRAMING AllocatorFraming;
+    ULONG Size;
+    NTSTATUS Status;
+    ULONG SupportedFlags;
+
+    /* set minimum request size */
+    Size = sizeof(KSALLOCATOR_FRAMING);
+
+    Status = KspCopyCreateRequest(Irp,
+                                  KSSTRING_Allocator,
+                                  &Size,
+                                  (PVOID*)&AllocatorFraming);
+
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* allowed supported flags */
+    SupportedFlags = (KSALLOCATOR_OPTIONF_COMPATIBLE | KSALLOCATOR_OPTIONF_SYSTEM_MEMORY |
+                      KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER | KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_FRAME_INTEGRITY | 
+                      KSALLOCATOR_REQUIREMENTF_MUST_ALLOCATE);
+
+
+    if (!AllocatorFraming->FrameSize || (AllocatorFraming->OptionsFlags & (~SupportedFlags)))
+    {
+        FreeItem(AllocatorFraming);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* store result */
+    *OutAllocatorFraming = AllocatorFraming;
+
+    return Status;
+}
+
+NTSTATUS
+IKsAllocator_DispatchRequest(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PFILE_OBJECT FileObject,
+    IN PIRP Irp,
+    IN PVOID Frame,
+    IN ALLOC_REQUEST Request)
+{
+    PKSIOBJECT_HEADER Header;
+    NTSTATUS Status;
+    IKsAllocator * Allocator;
+
+    /* sanity check */
+    ASSERT(FileObject);
+
+    /* get object header */
+    Header = (PKSIOBJECT_HEADER)FileObject->FsContext2;
+
+    /* get real allocator */
+    Status = Header->Unknown->lpVtbl->QueryInterface(Header->Unknown, &IID_IKsAllocator, (PVOID*)&Allocator);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* misbehaving object */
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (Request == ALLOCATOR_DEVICE_CONTROL)
+    {
+        /* dispatch request allocator */
+        Status = Allocator->lpVtbl->DispatchDeviceIoControl(Allocator, DeviceObject, Irp);
+    }
+    else if (Request == ALLOCATOR_DEVICE_CLOSE)
+    {
+        /* delete allocator */
+        Status = Allocator->lpVtbl->Close(Allocator);
+    }
+    else if (Request == ALLOCATOR_ALLOCATE)
+    {
+        /* allocate frame */
+        Status = Allocator->lpVtbl->AllocateFrame(Allocator, (PVOID*)Frame);
+
+    }else if (Request == ALLOCATOR_FREE)
+    {
+        /* allocate frame */
+        Allocator->lpVtbl->FreeFrame(Allocator, Frame);
+        Status = STATUS_SUCCESS;
+    }
+
+    /* release interface */
+    Allocator->lpVtbl->Release(Allocator);
+
+    return Status;
 }
 
+NTSTATUS
+NTAPI
+IKsAllocator_DispatchDeviceIoControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* dispatch request */
+    Status = IKsAllocator_DispatchRequest(DeviceObject, IoStack->FileObject, Irp, NULL, ALLOCATOR_DEVICE_CONTROL);
+
+    /* complete request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsAllocator_DispatchClose(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* dispatch request */
+    Status = IKsAllocator_DispatchRequest(DeviceObject, IoStack->FileObject, Irp, NULL, ALLOCATOR_DEVICE_CLOSE);
+
+    /* complete request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsAllocator_Allocate(
+    IN PFILE_OBJECT FileObject,
+    PVOID *Frame)
+{
+    NTSTATUS Status;
+
+    /* dispatch request */
+    Status = IKsAllocator_DispatchRequest(NULL, FileObject, NULL, (PVOID)Frame, ALLOCATOR_ALLOCATE);
+
+    return Status;
+}
+
+VOID
+NTAPI
+IKsAllocator_FreeFrame(
+    IN PFILE_OBJECT FileObject,
+    PVOID Frame)
+{
+    /* dispatch request */
+    IKsAllocator_DispatchRequest(NULL, FileObject, NULL, Frame, ALLOCATOR_FREE);
+}
+
+
+static KSDISPATCH_TABLE DispatchTable =
+{
+    IKsAllocator_DispatchDeviceIoControl,
+    KsDispatchInvalidDeviceRequest,
+    KsDispatchInvalidDeviceRequest,
+    KsDispatchInvalidDeviceRequest,
+    IKsAllocator_DispatchClose,
+    KsDispatchQuerySecurity,
+    KsDispatchSetSecurity,
+    KsDispatchFastIoDeviceControlFailure,
+    KsDispatchFastReadFailure,
+    KsDispatchFastReadFailure,
+};
+
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI NTSTATUS NTAPI
 KsCreateDefaultAllocatorEx(
@@ -54,12 +579,83 @@ KsCreateDefaultAllocatorEx(
     IN  PFNKSINITIALIZEALLOCATOR InitializeAllocator OPTIONAL,
     IN  PFNKSDELETEALLOCATOR DeleteAllocator OPTIONAL)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    NTSTATUS Status;
+    PKSALLOCATOR_FRAMING AllocatorFraming;
+    PALLOCATOR Allocator;
+    PVOID Ctx;
+
+    /* first validate connect request */
+    Status = KsValidateAllocatorCreateRequest(Irp, &AllocatorFraming);
+    if (!NT_SUCCESS(Status))
+        return STATUS_INVALID_PARAMETER;
+
+    /* check the valid file alignment */
+    if (AllocatorFraming->FileAlignment > (PAGE_SIZE-1))
+        return STATUS_INVALID_PARAMETER;
+
+    /* allocate allocator struct */
+    Allocator = AllocateItem(NonPagedPool, sizeof(ALLOCATOR));
+    if (!Allocator)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* allocate object header */
+    
+    Status = KsAllocateObjectHeader((KSOBJECT_HEADER*)&Allocator->Header, 0, NULL, Irp, &DispatchTable);
+    if (!NT_SUCCESS(Status))
+    {
+         FreeItem(Allocator);
+         return Status;
+    }
+
+    /* set allocator type in object header */
+    Allocator->lpVtbl = &vt_IKsAllocator;
+    Allocator->Header->Unknown = (PUNKNOWN)&Allocator->lpVtbl;
+    Allocator->ref = 1;
+
+    if (DefaultAllocate)
+    {
+        /* use external allocator */
+        Allocator->Type  = ALLOCATOR_CUSTOM;
+        Allocator->Allocate.DefaultAllocate = DefaultAllocate;
+        Allocator->Free.DefaultFree = DefaultFree;
+        Allocator->Delete.DefaultDelete = DeleteAllocator;
+        Ctx = InitializeAllocator(InitializeContext, AllocatorFraming, &Allocator->u.CustomList);
+        /* check for success */
+        if (!Ctx)
+        {
+            KsFreeObjectHeader(Allocator->Header);
+            FreeItem(Allocator);
+            return Status;
+        }
+    }
+    else if (AllocatorFraming->PoolType == NonPagedPool)
+    {
+        /* use non-paged pool allocator */
+        Allocator->Type  = ALLOCATOR_NPAGED_LOOKASIDE;
+        Allocator->Allocate.NPagedPool = ExAllocateFromNPagedLookasideList;
+        Allocator->Free.NPagedPool = ExFreeToNPagedLookasideList;
+        Allocator->Delete.NPagedPool = ExDeleteNPagedLookasideList;
+        ExInitializeNPagedLookasideList(&Allocator->u.NPagedList, NULL, NULL, 0, AllocatorFraming->FrameSize, 0, 0);
+    }
+    else if (AllocatorFraming->PoolType == PagedPool)
+    {
+        /* use paged pool allocator */
+        Allocator->Allocate.PagedPool = ExAllocateFromPagedLookasideList;
+        Allocator->Free.PagedPool = ExFreeToPagedLookasideList;
+        Allocator->Delete.PagedPool = ExDeletePagedLookasideList;
+        Allocator->Type  = ALLOCATOR_PAGED_LOOKASIDE;
+        ExInitializePagedLookasideList(&Allocator->u.PagedList, NULL, NULL, 0, AllocatorFraming->FrameSize, 0, 0);
+
+    }
+
+    /* backup allocator framing */
+    RtlMoveMemory(&Allocator->Status.Framing, AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
+
+    return Status;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI NTSTATUS NTAPI
 KsValidateAllocatorFramingEx(
@@ -67,6 +663,18 @@ KsValidateAllocatorFramingEx(
     IN  ULONG BufferSize,
     IN  const KSALLOCATOR_FRAMING_EX* PinFraming)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    if (BufferSize < sizeof(KSALLOCATOR_FRAMING_EX))
+       return  STATUS_INVALID_DEVICE_REQUEST;
+
+    /* verify framing */
+    if ((Framing->FramingItem[0].Flags & KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT) &&
+         Framing->OutputCompression.RatioNumerator != MAXULONG &&
+         Framing->OutputCompression.RatioDenominator != 0 &&
+         Framing->OutputCompression.RatioDenominator < Framing->OutputCompression.RatioNumerator)
+    {
+        /* framing request is ok */
+        return STATUS_SUCCESS;
+    }
+
+    return STATUS_INVALID_DEVICE_REQUEST;
 }