mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
allocators.c
- Implement IKsAllocator interface and use it in new implemented KsCreateAllocator, KsCreateDefaultAllocatorEx, KsValidateAllocatorFramingEx api.c - Implement KsSetDevicePnpAndBaseObject, KsQueryDevicePnpObject, KsSetTargetState, KsSetTargetDeviceObject, KsSetPowerDispatch, KsFreeDeviceHeader, KsFreeObjectHeader, KsAllocateObjectCreateItem, KsFreeObjectCreateItem, KsFreeObjectCreateItemsByContext, KsCreateDefaultSecurity clocks.c - Implement KsCreateClock, KsCreateDefaultClock, partly implement KsAllocateDefaultClockEx, KsFreeDefaultClock, KsGetDefaultClockState, KsSetDefaultClockState, KsGetDefaultClockTime, KsSetDefaultClockTime device.c - Partly implement IKsDevice interface in order to let AVStream client devices initialize - Implement KsInitializeDevice - Implement registering of device interface for AVStream drivers driver.c - Implement KsGetDeviceForDeviceObject - Set device flags for ks - Store Address for client drivers device extension filter.c - Implement IKsFilter & IKsControl interface - Handle KSPROPERTY requests filterfactory.c - Implement IKsFilterFactory interface - Implement KsCreateFilterFactory, KsFilterFactorySetDeviceClassesState, KsFilterFactoryGetSymbolicLink, KsFilterFactoryAddCreateItem - Add KsFilterFactoryUpdateCacheData image.c - Implement KsLoadResource irp.c - Implement KsDispatchQuerySecurity, KsDispatchSetSecurity, KsWriteFile, KsDefaultIoCompletion svn path=/trunk/; revision=42109
This commit is contained in:
parent
928ed84e9f
commit
764ee24fea
24 changed files with 5471 additions and 1637 deletions
|
@ -1,8 +1,365 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* unhandeled 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
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsCreateAllocator(
|
||||
|
@ -10,8 +367,12 @@ KsCreateAllocator(
|
|||
IN PKSALLOCATOR_FRAMING AllocatorFraming,
|
||||
OUT PHANDLE AllocatorHandle)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
return KspCreateObjectType(ConnectionHandle,
|
||||
L"{642F5D00-4791-11D0-A5D6-28DB04C10000}", //KSNAME_Allocator
|
||||
(PVOID)AllocatorFraming,
|
||||
sizeof(KSALLOCATOR_FRAMING),
|
||||
GENERIC_READ,
|
||||
AllocatorHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,8 +397,146 @@ KsValidateAllocatorCreateRequest(
|
|||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
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->FsContext;
|
||||
|
||||
/* 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(
|
||||
|
@ -50,17 +549,91 @@ KsCreateDefaultAllocatorEx(
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PKSALLOCATOR_FRAMING AllocatorFraming;
|
||||
PALLOCATOR Allocator;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
PVOID Ctx;
|
||||
|
||||
Status = KsValidateAllocatorCreateRequest(Irp, &AllocatorFraming);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
/* 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;
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
/* 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));
|
||||
|
||||
/* get create item */
|
||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||
|
||||
if (CreateItem)
|
||||
{
|
||||
/* store create item */
|
||||
Allocator->Header->CreateItem = CreateItem;
|
||||
Allocator->Header->ItemCount = 1;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsValidateAllocatorFramingEx(
|
||||
|
@ -68,6 +641,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 != (ULONG)-1 &&
|
||||
Framing->OutputCompression.RatioDenominator != 0 &&
|
||||
Framing->OutputCompression.RatioDenominator < Framing->OutputCompression.RatioNumerator)
|
||||
{
|
||||
/* framing request is ok */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
|
993
reactos/drivers/ksfilter/ks/api.c
Normal file
993
reactos/drivers/ksfilter/ks/api.c
Normal file
|
@ -0,0 +1,993 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/api.c
|
||||
* PURPOSE: KS API functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAcquireResetValue(
|
||||
IN PIRP Irp,
|
||||
OUT KSRESET* ResetValue)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsAcquireDeviceSecurityLock(
|
||||
IN KSDEVICE_HEADER DevHeader,
|
||||
IN BOOLEAN Exclusive)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (Exclusive)
|
||||
{
|
||||
Status = ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsReleaseDeviceSecurityLock(
|
||||
IN KSDEVICE_HEADER DevHeader)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
ExReleaseResourceLite(&Header->SecurityLock);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsDefaultDispatchPnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//FIXME
|
||||
//REWRITE
|
||||
|
||||
DPRINT1("KsDefaultDispatchPnp entered with func %x\n", IoStack->MinorFunction);
|
||||
|
||||
switch(IoStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
// FIXME
|
||||
// destroy device header, detach device and delete device
|
||||
case IRP_MN_START_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
default:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
//Status = IoCallDriver(NULL /* PnpBaseObject */, Irp);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsDefaultDispatchPower(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsDefaultForwardIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetDevicePnpAndBaseObject(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PDEVICE_OBJECT PnpDeviceObject,
|
||||
IN PDEVICE_OBJECT BaseDevice)
|
||||
{
|
||||
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
|
||||
|
||||
DeviceHeader->PhysicalDeviceObject = PnpDeviceObject;
|
||||
DeviceHeader->NextDeviceObject = BaseDevice;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
PDEVICE_OBJECT
|
||||
NTAPI
|
||||
KsQueryDevicePnpObject(
|
||||
IN KSDEVICE_HEADER Header)
|
||||
{
|
||||
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
|
||||
|
||||
/* return next device header */
|
||||
return DeviceHeader->NextDeviceObject;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
ACCESS_MASK
|
||||
NTAPI
|
||||
KsQueryObjectAccessMask(
|
||||
IN KSOBJECT_HEADER Header)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsRecalculateStackDepth(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN BOOLEAN ReuseStackLocation)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetTargetState(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN KSTARGET_STATE TargetState)
|
||||
{
|
||||
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
|
||||
|
||||
/* set target state */
|
||||
DeviceHeader->TargetState = TargetState;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetTargetDeviceObject(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN PDEVICE_OBJECT TargetDevice OPTIONAL)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
|
||||
|
||||
if(ObjectHeader->TargetDevice)
|
||||
{
|
||||
/* there is already a target device set */
|
||||
if (!TargetDevice)
|
||||
{
|
||||
/* caller wants to remove the target device */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension;
|
||||
|
||||
/* get device header */
|
||||
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
|
||||
|
||||
/* acquire lock */
|
||||
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
|
||||
|
||||
/* remove entry */
|
||||
RemoveEntryList(&ObjectHeader->TargetDeviceListEntry);
|
||||
|
||||
/* remove device pointer */
|
||||
ObjectHeader->TargetDevice = NULL;
|
||||
|
||||
/* release lock */
|
||||
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no target device yet set */
|
||||
if (TargetDevice)
|
||||
{
|
||||
/* caller wants to add the target device */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension;
|
||||
|
||||
/* get device header */
|
||||
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
|
||||
|
||||
/* acquire lock */
|
||||
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
|
||||
|
||||
/* insert list entry */
|
||||
InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry);
|
||||
|
||||
/* store target device */
|
||||
ObjectHeader->TargetDevice = TargetDevice;
|
||||
|
||||
/* release lock */
|
||||
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetPowerDispatch(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
|
||||
IN PVOID PowerContext OPTIONAL)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
|
||||
|
||||
/* caller wants to add the target device */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension;
|
||||
|
||||
/* get device header */
|
||||
DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
|
||||
|
||||
/* acquire lock */
|
||||
KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
|
||||
|
||||
if (PowerDispatch)
|
||||
{
|
||||
/* add power dispatch entry */
|
||||
InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry);
|
||||
|
||||
/* store function and context */
|
||||
ObjectHeader->PowerDispatch = PowerDispatch;
|
||||
ObjectHeader->PowerContext = PowerContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* remove power dispatch entry */
|
||||
RemoveEntryList(&ObjectHeader->PowerDispatchEntry);
|
||||
|
||||
/* store function and context */
|
||||
ObjectHeader->PowerDispatch = NULL;
|
||||
ObjectHeader->PowerContext = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* release lock */
|
||||
KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
PKSOBJECT_CREATE_ITEM
|
||||
NTAPI
|
||||
KsQueryObjectCreateItem(
|
||||
IN KSOBJECT_HEADER Header)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAllocateDeviceHeader(
|
||||
OUT KSDEVICE_HEADER* OutHeader,
|
||||
IN ULONG ItemsCount,
|
||||
IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
|
||||
{
|
||||
ULONG Index = 0;
|
||||
PKSIDEVICE_HEADER Header;
|
||||
|
||||
if (!OutHeader)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* allocate a device header */
|
||||
Header = ExAllocatePoolWithTag(PagedPool, sizeof(KSIDEVICE_HEADER), TAG_DEVICE_HEADER);
|
||||
|
||||
/* check for success */
|
||||
if (!Header)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* clear all memory */
|
||||
RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
|
||||
|
||||
/* initialize spin lock */
|
||||
KeInitializeSpinLock(&Header->ItemListLock); //FIXME
|
||||
|
||||
/* initialize device mutex */
|
||||
KeInitializeMutex(&Header->DeviceMutex, 0);
|
||||
|
||||
/* initialize target device list */
|
||||
InitializeListHead(&Header->TargetDeviceList);
|
||||
/* initialize power dispatch list */
|
||||
InitializeListHead(&Header->PowerDispatchList);
|
||||
|
||||
/* are there any create items provided */
|
||||
if (ItemsCount && ItemsList)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
for(Index = 0; Index < ItemsCount; Index++)
|
||||
{
|
||||
/* store provided create items */
|
||||
Header->ItemList[Index].CreateItem = &ItemsList[Index];
|
||||
}
|
||||
Header->MaxItems = ItemsCount;
|
||||
}
|
||||
|
||||
/* store result */
|
||||
*OutHeader = Header;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsFreeDeviceHeader(
|
||||
IN KSDEVICE_HEADER DevHeader)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header;
|
||||
|
||||
Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
if (!DevHeader)
|
||||
return;
|
||||
|
||||
ExFreePoolWithTag(Header->ItemList, TAG_DEVICE_HEADER);
|
||||
ExFreePoolWithTag(Header, TAG_DEVICE_HEADER);
|
||||
}
|
||||
|
||||
/*
|
||||
@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)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
|
||||
if (!Header)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
if (!Irp)
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
|
||||
if (!Table)
|
||||
return STATUS_INVALID_PARAMETER_5;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(IoStack->FileObject);
|
||||
/* check for an file object */
|
||||
|
||||
/* allocate the object header */
|
||||
ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
|
||||
if (!ObjectHeader)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* initialize object header */
|
||||
RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
|
||||
|
||||
/* do we have a name */
|
||||
if (IoStack->FileObject->FileName.Buffer)
|
||||
{
|
||||
/* copy object class */
|
||||
ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
|
||||
ObjectHeader->ObjectClass.Buffer = ExAllocatePoolWithTag(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength, TAG_DEVICE_HEADER);
|
||||
if (!ObjectHeader->ObjectClass.Buffer)
|
||||
{
|
||||
ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
|
||||
}
|
||||
|
||||
/* copy dispatch table */
|
||||
RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
|
||||
/* store create items */
|
||||
if (ItemsCount && ItemsList)
|
||||
{
|
||||
ObjectHeader->ItemCount = ItemsCount;
|
||||
ObjectHeader->CreateItem = ItemsList;
|
||||
}
|
||||
|
||||
/* store the object in the file object */
|
||||
ASSERT(IoStack->FileObject->FsContext == NULL);
|
||||
IoStack->FileObject->FsContext = ObjectHeader;
|
||||
|
||||
/* the object header is for a audio filter */
|
||||
ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
|
||||
|
||||
/* store parent device */
|
||||
ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
|
||||
|
||||
/* store result */
|
||||
*Header = ObjectHeader;
|
||||
|
||||
|
||||
|
||||
DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsFreeObjectHeader(
|
||||
IN PVOID Header)
|
||||
{
|
||||
PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
|
||||
|
||||
if (ObjectHeader->ObjectClass.Buffer)
|
||||
{
|
||||
/* release object class buffer */
|
||||
ExFreePoolWithTag(ObjectHeader->ObjectClass.Buffer, TAG_DEVICE_HEADER);
|
||||
}
|
||||
|
||||
if (ObjectHeader->Unknown)
|
||||
{
|
||||
/* release associated object */
|
||||
ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
|
||||
}
|
||||
|
||||
/* FIXME free create items */
|
||||
|
||||
/* free object header */
|
||||
ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAddObjectCreateItemToDeviceHeader(
|
||||
IN KSDEVICE_HEADER DevHeader,
|
||||
IN PDRIVER_DISPATCH Create,
|
||||
IN PVOID Context,
|
||||
IN PWCHAR ObjectClass,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header;
|
||||
ULONG FreeIndex, Index;
|
||||
|
||||
Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
DPRINT1("KsAddObjectCreateItemToDeviceHeader entered\n");
|
||||
|
||||
/* check if a device header has been provided */
|
||||
if (!DevHeader)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
/* check if a create item has been provided */
|
||||
if (!Create)
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
|
||||
/* check if a object class has been provided */
|
||||
if (!ObjectClass)
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
|
||||
FreeIndex = (ULONG)-1;
|
||||
/* now scan the list and check for a free item */
|
||||
for(Index = 0; Index < Header->MaxItems; Index++)
|
||||
{
|
||||
ASSERT(Header->ItemList[Index].CreateItem);
|
||||
|
||||
if (Header->ItemList[Index].CreateItem->Create == NULL)
|
||||
{
|
||||
FreeIndex = Index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wcsicmp(ObjectClass, Header->ItemList[Index].CreateItem->ObjectClass.Buffer))
|
||||
{
|
||||
/* the same object class already exists */
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
}
|
||||
/* found a free index */
|
||||
if (FreeIndex == (ULONG)-1)
|
||||
{
|
||||
/* no empty space found */
|
||||
return STATUS_ALLOTTED_SPACE_EXCEEDED;
|
||||
}
|
||||
|
||||
/* initialize create item */
|
||||
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;
|
||||
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAddObjectCreateItemToObjectHeader(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN PDRIVER_DISPATCH Create,
|
||||
IN PVOID Context,
|
||||
IN PWCHAR ObjectClass,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAllocateObjectCreateItem(
|
||||
IN KSDEVICE_HEADER DevHeader,
|
||||
IN PKSOBJECT_CREATE_ITEM CreateItem,
|
||||
IN BOOLEAN AllocateEntry,
|
||||
IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header;
|
||||
PKSOBJECT_CREATE_ITEM Item;
|
||||
PDEVICE_ITEM ItemList;
|
||||
KIRQL OldLevel;
|
||||
|
||||
Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
if (!DevHeader)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
if (!CreateItem)
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
|
||||
/* acquire list lock */
|
||||
KeAcquireSpinLock(&Header->ItemListLock, &OldLevel);
|
||||
|
||||
ItemList = ExAllocatePool(NonPagedPool, sizeof(DEVICE_ITEM) * (Header->MaxItems + 1));
|
||||
if (!ItemList)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
if (AllocateEntry)
|
||||
{
|
||||
if (!ItemFreeCallback)
|
||||
{
|
||||
/* caller must be notified */
|
||||
ExFreePool(ItemList);
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
|
||||
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
}
|
||||
/* allocate create item */
|
||||
Item = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||
if (!Item)
|
||||
{
|
||||
/* no memory */
|
||||
ExFreePool(ItemList);
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* initialize descriptor */
|
||||
Item->Context = CreateItem->Context;
|
||||
Item->Create = CreateItem->Create;
|
||||
Item->Flags = CreateItem->Flags;
|
||||
Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
|
||||
Item->ObjectClass.Length = 0;
|
||||
Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
|
||||
|
||||
/* copy object class */
|
||||
Item->ObjectClass.Buffer = ExAllocatePool(NonPagedPool, Item->ObjectClass.MaximumLength);
|
||||
if (!Item->ObjectClass.Buffer)
|
||||
{
|
||||
/* release resources */
|
||||
ExFreePool(Item);
|
||||
ExFreePool(ItemList);
|
||||
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ItemFreeCallback)
|
||||
{
|
||||
/* callback is only accepted when the create item is copied */
|
||||
ExFreePool(ItemList);
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
|
||||
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
}
|
||||
|
||||
Item = CreateItem;
|
||||
}
|
||||
|
||||
|
||||
if (Header->MaxItems)
|
||||
{
|
||||
/* copy old create items */
|
||||
RtlMoveMemory(ItemList, Header->ItemList, sizeof(DEVICE_ITEM) * Header->MaxItems);
|
||||
}
|
||||
|
||||
/* initialize item entry */
|
||||
ItemList[Header->MaxItems].CreateItem = Item;
|
||||
ItemList[Header->MaxItems].ItemFreeCallback = ItemFreeCallback;
|
||||
|
||||
|
||||
/* free old item list */
|
||||
ExFreePool(Header->ItemList);
|
||||
|
||||
Header->ItemList = ItemList;
|
||||
Header->MaxItems++;
|
||||
|
||||
/* release lock */
|
||||
KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspObjectFreeCreateItems(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PKSOBJECT_CREATE_ITEM CreateItem)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsFreeObjectCreateItem(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PUNICODE_STRING CreateItem)
|
||||
{
|
||||
KSOBJECT_CREATE_ITEM Item;
|
||||
|
||||
RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
|
||||
RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
|
||||
|
||||
return KspObjectFreeCreateItems(Header, &Item);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsFreeObjectCreateItemsByContext(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PVOID Context)
|
||||
{
|
||||
KSOBJECT_CREATE_ITEM Item;
|
||||
|
||||
RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
|
||||
|
||||
Item.Context = Context;
|
||||
|
||||
return KspObjectFreeCreateItems(Header, &Item);
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsCreateDefaultSecurity(
|
||||
IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
|
||||
OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
|
||||
{
|
||||
PGENERIC_MAPPING Mapping;
|
||||
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* start capturing security context of calling thread */
|
||||
SeCaptureSubjectContext(&SubjectContext);
|
||||
/* get generic mapping */
|
||||
Mapping = IoGetFileObjectGenericMapping();
|
||||
/* build new descriptor */
|
||||
Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
|
||||
/* release security descriptor */
|
||||
SeReleaseSubjectContext(&SubjectContext);
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsForwardIrp(
|
||||
IN PIRP Irp,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN BOOLEAN ReuseStackLocation)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsForwardAndCatchIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN KSSTACK_USE StackUse)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspSynchronousIoControlDeviceCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
|
||||
|
||||
IoStatusBlock->Information = Irp->IoStatus.Information;
|
||||
IoStatusBlock->Status = Irp->IoStatus.Status;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsSynchronousIoControlDevice(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN KPROCESSOR_MODE RequestorMode,
|
||||
IN ULONG IoControl,
|
||||
IN PVOID InBuffer,
|
||||
IN ULONG InSize,
|
||||
OUT PVOID OutBuffer,
|
||||
IN ULONG OutSize,
|
||||
OUT PULONG BytesReturned)
|
||||
{
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* check for valid file object */
|
||||
if (!FileObject)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* get device object to send the request to */
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
if (!DeviceObject)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
||||
/* get object header */
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
|
||||
/* check if there is fast device io function */
|
||||
if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
|
||||
{
|
||||
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
||||
IoStatusBlock.Information = 0;
|
||||
|
||||
/* it is send the request */
|
||||
Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
|
||||
/* check if the request was handled */
|
||||
DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
|
||||
if (Status)
|
||||
{
|
||||
/* store bytes returned */
|
||||
*BytesReturned = IoStatusBlock.Information;
|
||||
/* return status */
|
||||
return IoStatusBlock.Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* create the irp */
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
|
||||
|
||||
/* HACK */
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->FileObject = FileObject;
|
||||
|
||||
IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
*BytesReturned = IoStatusBlock.Information;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsUnserializeObjectPropertiesFromRegistry(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN HANDLE ParentKey OPTIONAL,
|
||||
IN PUNICODE_STRING RegistryPath OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsCacheMedium(
|
||||
IN PUNICODE_STRING SymbolicLink,
|
||||
IN PKSPIN_MEDIUM Medium,
|
||||
IN ULONG PinDirection)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/bag.c
|
||||
* PURPOSE: KS Object Bag functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,43 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/clocks.c
|
||||
* PURPOSE: KS Clocks functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LONGLONG Time;
|
||||
KSPIN_LOCK TimeLock;
|
||||
KSSTATE State;
|
||||
KTIMER Timer;
|
||||
LONG ReferenceCount;
|
||||
|
||||
PVOID Context;
|
||||
PFNKSSETTIMER SetTimer;
|
||||
PFNKSCANCELTIMER CancelTimer;
|
||||
PFNKSCORRELATEDTIME CorrelatedTime;
|
||||
KSRESOLUTION* Resolution;
|
||||
ULONG Flags;
|
||||
|
||||
}KSIDEFAULTCLOCK, *PKSIDEFAULTCLOCK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IKsClock *lpVtbl;
|
||||
LONG ref;
|
||||
PKSCLOCK_CREATE ClockCreate;
|
||||
PKSIDEFAULTCLOCK DefaultClock;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
}KSICLOCK, *PKSICLOCK;
|
||||
|
||||
}KS_DEFAULT_CLOCK;
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsCreateClock(
|
||||
|
@ -14,36 +45,136 @@ KsCreateClock(
|
|||
IN PKSCLOCK_CREATE ClockCreate,
|
||||
OUT PHANDLE ClockHandle)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
return KspCreateObjectType(ConnectionHandle,
|
||||
L"{53172480-4791-11D0-A5D6-28DB04C10000}", /* KSName_Clock */
|
||||
ClockCreate,
|
||||
sizeof(KSCLOCK_CREATE),
|
||||
GENERIC_READ,
|
||||
ClockHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsValidateClockCreateRequest(
|
||||
IN PIRP Irp,
|
||||
OUT PKSCLOCK_CREATE* ClockCreate)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsClock_DispatchDeviceIoControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsClock_DispatchClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static KSDISPATCH_TABLE DispatchTable =
|
||||
{
|
||||
IKsClock_DispatchDeviceIoControl,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
IKsClock_DispatchClose,
|
||||
KsDispatchQuerySecurity,
|
||||
KsDispatchSetSecurity,
|
||||
KsDispatchFastIoDeviceControlFailure,
|
||||
KsDispatchFastReadFailure,
|
||||
KsDispatchFastReadFailure,
|
||||
};
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsCreateDefaultClock(
|
||||
IN PIRP Irp,
|
||||
IN PKSDEFAULTCLOCK DefaultClock)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKSCLOCK_CREATE ClockCreate;
|
||||
PKSICLOCK Clock;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
Status = KsValidateClockCreateRequest(Irp, &ClockCreate);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
// ExAllocatePoolWithTag(NonPagedPool, sizeof(KS_DEFAULT_CLOCK), 0);
|
||||
/* let's allocate the clock struct */
|
||||
Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
|
||||
if (!Clock)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* now allocate the object header */
|
||||
Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
|
||||
|
||||
/* did it work */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
FreeItem(Clock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
/* initialize clock */
|
||||
/* FIXME IKsClock */
|
||||
Clock->ObjectHeader->Unknown = (PUNKNOWN)&Clock->lpVtbl;
|
||||
Clock->ref = 1;
|
||||
Clock->ClockCreate = ClockCreate;
|
||||
Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
|
||||
/* increment reference count */
|
||||
InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
|
||||
|
||||
/* get create item */
|
||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||
|
||||
if (CreateItem)
|
||||
{
|
||||
/* store create item */
|
||||
Clock->ObjectHeader->CreateItem = CreateItem;
|
||||
Clock->ObjectHeader->ItemCount = 1;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAllocateDefaultClock(
|
||||
OUT PKSDEFAULTCLOCK* DefaultClock)
|
||||
{
|
||||
|
@ -53,7 +184,9 @@ KsAllocateDefaultClock(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsAllocateDefaultClockEx(
|
||||
OUT PKSDEFAULTCLOCK* DefaultClock,
|
||||
IN PVOID Context OPTIONAL,
|
||||
|
@ -63,72 +196,113 @@ KsAllocateDefaultClockEx(
|
|||
IN const KSRESOLUTION* Resolution OPTIONAL,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
PKSIDEFAULTCLOCK Clock;
|
||||
|
||||
if (!DefaultClock)
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
|
||||
/* allocate default clock */
|
||||
Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
|
||||
if (!Clock)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* initialize default clock */
|
||||
KeInitializeSpinLock(&Clock->TimeLock);
|
||||
KeInitializeTimer(&Clock->Timer);
|
||||
Clock->ReferenceCount = 1;
|
||||
Clock->Context = Context;
|
||||
Clock->SetTimer = SetTimer;
|
||||
Clock->CancelTimer = CancelTimer;
|
||||
Clock->CorrelatedTime = CorrelatedTime;
|
||||
Clock->Resolution = (PKSRESOLUTION)Resolution;
|
||||
Clock->Flags = Flags;
|
||||
|
||||
*DefaultClock = (PKSDEFAULTCLOCK)Clock;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsFreeDefaultClock(
|
||||
IN PKSDEFAULTCLOCK DefaultClock)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
|
||||
InterlockedDecrement(&Clock->ReferenceCount);
|
||||
|
||||
if (Clock->ReferenceCount == 0)
|
||||
{
|
||||
/* free default clock */
|
||||
FreeItem(Clock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsValidateClockCreateRequest(
|
||||
IN PIRP Irp,
|
||||
OUT PKSCLOCK_CREATE* ClockCreate)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI KSSTATE NTAPI
|
||||
KSDDKAPI
|
||||
KSSTATE
|
||||
NTAPI
|
||||
KsGetDefaultClockState(
|
||||
IN PKSDEFAULTCLOCK DefaultClock)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
return Clock->State;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetDefaultClockState(
|
||||
IN PKSDEFAULTCLOCK DefaultClock,
|
||||
IN KSSTATE State)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
|
||||
if (State != Clock->State)
|
||||
{
|
||||
/* FIXME set time etc */
|
||||
Clock->State = State;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI LONGLONG NTAPI
|
||||
KSDDKAPI
|
||||
LONGLONG
|
||||
NTAPI
|
||||
KsGetDefaultClockTime(
|
||||
IN PKSDEFAULTCLOCK DefaultClock)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
LONGLONG Time = 0LL;
|
||||
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
|
||||
Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
|
||||
|
||||
return Time;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsSetDefaultClockTime(
|
||||
IN PKSDEFAULTCLOCK DefaultClock,
|
||||
IN LONGLONG Time)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
|
||||
|
||||
/* set the time safely */
|
||||
ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/connectivity.c
|
||||
* PURPOSE: KS Pin functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/*
|
||||
|
@ -437,9 +446,13 @@ KsPinDataIntersection(
|
|||
return STATUS_NO_MATCH;
|
||||
}
|
||||
|
||||
/* Does this belong here? */
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsHandleSizedListQuery(
|
||||
IN PIRP Irp,
|
||||
IN ULONG DataItemsCount,
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/device.c
|
||||
* PURPOSE: KS IKsDevice interface functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IKsDeviceVtbl *lpVtbl;
|
||||
|
||||
LONG ref;
|
||||
KSDEVICE KsDevice;
|
||||
|
||||
}IKsDeviceImpl;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_fnQueryInterface(
|
||||
IN IKsDevice * iface,
|
||||
REFIID InterfaceId,
|
||||
PVOID* Interface)
|
||||
REFIID refiid,
|
||||
PVOID* Output)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnQueryInterface %p\n", This);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||
{
|
||||
*Output = &This->lpVtblIKsDevice;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
ULONG
|
||||
|
@ -28,7 +33,7 @@ NTAPI
|
|||
IKsDevice_fnAddRef(
|
||||
IN IKsDevice * iface)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
@ -38,27 +43,21 @@ NTAPI
|
|||
IKsDevice_fnRelease(
|
||||
IN IKsDevice * iface)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
InterlockedDecrement(&This->ref);
|
||||
|
||||
if (This->ref == 0)
|
||||
{
|
||||
ExFreePoolWithTag(This, TAG_KSDEVICE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
|
||||
|
||||
KSDEVICE *
|
||||
PKSDEVICE
|
||||
NTAPI
|
||||
IKsDevice_fnGetStruct(
|
||||
IN IKsDevice * iface)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
return &This->KsDevice;
|
||||
}
|
||||
|
@ -70,9 +69,9 @@ IKsDevice_fnInitializeObjectBag(
|
|||
IN struct KSIOBJECTBAG *Bag,
|
||||
IN KMUTANT * Mutant)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnInitializeObjectBag %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -81,10 +80,9 @@ NTAPI
|
|||
IKsDevice_fnAcquireDevice(
|
||||
IN IKsDevice * iface)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnAcquireDevice %p\n", This);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return KeWaitForSingleObject(&This->DeviceMutex, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -92,10 +90,9 @@ NTAPI
|
|||
IKsDevice_fnReleaseDevice(
|
||||
IN IKsDevice * iface)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnReleaseDevice %p\n", This);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return KeReleaseMutex(&This->DeviceMutex, FALSE);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -106,9 +103,9 @@ IKsDevice_fnGetAdapterObject(
|
|||
IN PULONG Unknown1,
|
||||
IN PULONG Unknown2)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnGetAdapterObject %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
}
|
||||
|
@ -120,9 +117,9 @@ IKsDevice_fnAddPowerEntry(
|
|||
IN struct KSPOWER_ENTRY * Entry,
|
||||
IN IKsPowerNotify* Notify)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnAddPowerEntry %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -132,9 +129,9 @@ IKsDevice_fnRemovePowerEntry(
|
|||
IN IKsDevice * iface,
|
||||
IN struct KSPOWER_ENTRY * Entry)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnRemovePowerEntry %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
}
|
||||
|
@ -148,9 +145,9 @@ IKsDevice_fnPinStateChange(
|
|||
IN KSSTATE OldState,
|
||||
IN KSSTATE NewState)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnPinStateChange %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
}
|
||||
|
@ -163,9 +160,9 @@ IKsDevice_fnArbitrateAdapterChannel(
|
|||
IN IO_ALLOCATION_ACTION Action,
|
||||
IN PVOID Context)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnArbitrateAdapterChannel %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
}
|
||||
|
@ -176,9 +173,9 @@ IKsDevice_fnCheckIoCapability(
|
|||
IN IKsDevice * iface,
|
||||
IN ULONG Unknown)
|
||||
{
|
||||
IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
|
||||
//PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
|
||||
|
||||
DPRINT1("IKsDevice_fnCheckIoCapability %p\n", This);
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -200,21 +197,487 @@ static IKsDeviceVtbl vt_IKsDevice =
|
|||
};
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsDevice_PnpPostStart(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PPNP_POSTSTART_CONTEXT Ctx = (PPNP_POSTSTART_CONTEXT)Context;
|
||||
|
||||
/* call driver pnp post routine */
|
||||
Status = Ctx->DeviceHeader->Descriptor->Dispatch->PostStart(&Ctx->DeviceHeader->KsDevice);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Driver: PostStart Routine returned %x\n", Status);
|
||||
|
||||
/* set state to disabled */
|
||||
Ctx->DeviceHeader->TargetState = KSTARGET_STATE_DISABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set state to enabled */
|
||||
Ctx->DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
|
||||
}
|
||||
|
||||
/* free work item */
|
||||
IoFreeWorkItem(Ctx->WorkItem);
|
||||
|
||||
/* free work context */
|
||||
FreeItem(Ctx);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NewIKsDevice(IKsDevice** OutDevice)
|
||||
IKsDevice_PnpStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
IKsDeviceImpl * This;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PPNP_POSTSTART_CONTEXT Ctx = NULL;
|
||||
NTSTATUS Status;
|
||||
|
||||
This = ExAllocatePoolWithTag(NonPagedPool, sizeof(IKsDeviceImpl), TAG_KSDEVICE);
|
||||
if (!This)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
This->ref = 1;
|
||||
This->lpVtbl = &vt_IKsDevice;
|
||||
/* first forward irp to lower device object */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NextDevice object failed to start with %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* do we have a device descriptor */
|
||||
if (DeviceHeader->Descriptor)
|
||||
{
|
||||
/* does the device want pnp notifications */
|
||||
if (DeviceHeader->Descriptor->Dispatch)
|
||||
{
|
||||
/* does the driver care about IRP_MN_START_DEVICE */
|
||||
if (DeviceHeader->Descriptor->Dispatch->Start)
|
||||
{
|
||||
/* call driver start device routine */
|
||||
Status = DeviceHeader->Descriptor->Dispatch->Start(&DeviceHeader->KsDevice, Irp,
|
||||
IoStack->Parameters.StartDevice.AllocatedResourcesTranslated,
|
||||
IoStack->Parameters.StartDevice.AllocatedResources);
|
||||
|
||||
ASSERT(Status != STATUS_PENDING);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Driver: failed to start %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* set state to run */
|
||||
DeviceHeader->KsDevice.Started = TRUE;
|
||||
|
||||
}
|
||||
|
||||
/* does the driver need post start routine */
|
||||
if (DeviceHeader->Descriptor->Dispatch->PostStart)
|
||||
{
|
||||
/* allocate pnp post workitem context */
|
||||
Ctx = (PPNP_POSTSTART_CONTEXT)AllocateItem(NonPagedPool, sizeof(PNP_POSTSTART_CONTEXT));
|
||||
if (!Ctx)
|
||||
{
|
||||
/* no memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allocate a work item */
|
||||
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
|
||||
if (!Ctx->WorkItem)
|
||||
{
|
||||
/* no memory */
|
||||
FreeItem(Ctx);
|
||||
Ctx = NULL;
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* store device header for post-start pnp processing */
|
||||
Ctx->DeviceHeader = DeviceHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set state to enabled, IRP_MJ_CREATE request may now succeed */
|
||||
DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* store result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
/* complete request */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
if (Ctx)
|
||||
{
|
||||
/* queue a work item for driver post start routine */
|
||||
IoQueueWorkItem(Ctx->WorkItem, IKsDevice_PnpPostStart, DelayedWorkQueue, (PVOID)Ctx);
|
||||
}
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Pnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PKSDEVICE_DISPATCH Dispatch = NULL;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
/* do we have a device descriptor */
|
||||
if (DeviceHeader->Descriptor)
|
||||
{
|
||||
/* does the device want pnp notifications */
|
||||
Dispatch = (PKSDEVICE_DISPATCH)DeviceHeader->Descriptor->Dispatch;
|
||||
}
|
||||
|
||||
switch (IoStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
return IKsDevice_PnpStartDevice(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
/* check for pnp notification support */
|
||||
if (Dispatch)
|
||||
{
|
||||
/* check for query stop support */
|
||||
if (Dispatch->QueryStop)
|
||||
{
|
||||
/* call driver's query stop */
|
||||
Status = Dispatch->QueryStop(&DeviceHeader->KsDevice, Irp);
|
||||
ASSERT(Status != STATUS_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Driver: query stop failed %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
/* Clean up */
|
||||
if (Dispatch)
|
||||
{
|
||||
/* check for remove support */
|
||||
if (Dispatch->Remove)
|
||||
{
|
||||
/* call driver's stop routine */
|
||||
Dispatch->Remove(&DeviceHeader->KsDevice, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
/* FIXME delete device resources */
|
||||
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_INTERFACE:
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
/* check for pnp notification support */
|
||||
if (Dispatch)
|
||||
{
|
||||
/* check for query interface support */
|
||||
if (Dispatch->QueryInterface)
|
||||
{
|
||||
/* call driver's query interface */
|
||||
Status = Dispatch->QueryInterface(&DeviceHeader->KsDevice, Irp);
|
||||
ASSERT(Status != STATUS_PENDING);
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* driver supports a private interface */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
|
||||
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
||||
{
|
||||
DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
||||
{
|
||||
DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
|
||||
/* pass the irp down the driver stack */
|
||||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
default:
|
||||
DPRINT1("unhandled function %u\n", IoStack->MinorFunction);
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Power(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
/* TODO */
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
*OutDevice = (IKsDevice*)This;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Create(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
ULONG Index;
|
||||
NTSTATUS Status;
|
||||
ULONG Length;
|
||||
|
||||
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;
|
||||
|
||||
/* acquire list lock */
|
||||
IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->lpVtblIKsDevice);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(IoStack->FileObject);
|
||||
|
||||
/* loop all device items */
|
||||
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
|
||||
{
|
||||
/* is there a create item */
|
||||
if (DeviceHeader->ItemList[Index].CreateItem == NULL)
|
||||
continue;
|
||||
|
||||
/* check if the create item is initialized */
|
||||
if (!DeviceHeader->ItemList[Index].CreateItem->Create)
|
||||
continue;
|
||||
|
||||
ASSERT(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer);
|
||||
DPRINT("CreateItem %p Request %S\n", DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer,
|
||||
IoStack->FileObject->FileName.Buffer);
|
||||
|
||||
/* get object class length */
|
||||
Length = wcslen(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer);
|
||||
/* now check if the object class is the same */
|
||||
if (!_wcsnicmp(DeviceHeader->ItemList[Index].CreateItem->ObjectClass.Buffer, &IoStack->FileObject->FileName.Buffer[1], Length) ||
|
||||
(DeviceHeader->ItemList[Index].CreateItem->Flags & KSCREATE_ITEM_WILDCARD))
|
||||
{
|
||||
/* setup create parameters */
|
||||
DeviceHeader->DeviceIndex = Index;
|
||||
/* set object create item */
|
||||
KSCREATE_ITEM_IRP_STORAGE(Irp) = DeviceHeader->ItemList[Index].CreateItem;
|
||||
|
||||
/* call create function */
|
||||
Status = DeviceHeader->ItemList[Index].CreateItem->Create(DeviceObject, Irp);
|
||||
|
||||
/* release lock */
|
||||
IKsDevice_fnRelease((IKsDevice*)&DeviceHeader->lpVtblIKsDevice);
|
||||
|
||||
/* did we succeed */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* increment create item reference count */
|
||||
InterlockedIncrement((PLONG)&DeviceHeader->ItemList[Index].ReferenceCount);
|
||||
}
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* release lock */
|
||||
IKsDevice_fnRelease((IKsDevice*)&DeviceHeader->lpVtblIKsDevice);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
/* set return status */
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsInitializeDevice(
|
||||
IN PDEVICE_OBJECT FunctionalDeviceObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDEVICE_OBJECT NextDeviceObject,
|
||||
IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header;
|
||||
ULONG Index;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* first allocate device header */
|
||||
Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&Header, 0, NULL);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to allocate device header with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* initialize device header */
|
||||
Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
|
||||
Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
|
||||
Header->KsDevice.NextDeviceObject = NextDeviceObject;
|
||||
Header->KsDevice.Descriptor = Descriptor;
|
||||
KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
|
||||
/* initialize IKsDevice interface */
|
||||
Header->lpVtblIKsDevice = &vt_IKsDevice;
|
||||
Header->ref = 1;
|
||||
|
||||
/* FIXME Power state */
|
||||
|
||||
if (Descriptor)
|
||||
{
|
||||
/* create a filter factory for each filter descriptor */
|
||||
for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
|
||||
{
|
||||
Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
|
||||
/* FIXME memory leak */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* does the driver pnp notification */
|
||||
if (Descriptor->Dispatch)
|
||||
{
|
||||
/* does the driver care about the add device */
|
||||
Status = Descriptor->Dispatch->Add(&Header->KsDevice);
|
||||
|
||||
DPRINT("Driver: AddHandler Status %x\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
98
reactos/drivers/ksfilter/ks/deviceinterface.c
Normal file
98
reactos/drivers/ksfilter/ks/deviceinterface.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "priv.h"
|
||||
|
||||
NTSTATUS
|
||||
KspSetDeviceInterfacesState(
|
||||
IN PLIST_ENTRY ListHead,
|
||||
IN BOOL Enable)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PLIST_ENTRY Entry;
|
||||
PSYMBOLIC_LINK_ENTRY SymEntry;
|
||||
|
||||
|
||||
Entry = ListHead->Flink;
|
||||
while(Entry != ListHead)
|
||||
{
|
||||
/* fetch symbolic link entry */
|
||||
SymEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLIC_LINK_ENTRY, Entry);
|
||||
/* set device interface state */
|
||||
Status = IoSetDeviceInterfaceState(&SymEntry->SymbolicLink, Enable);
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
/* get next entry */
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspFreeDeviceInterfaces(
|
||||
IN PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PSYMBOLIC_LINK_ENTRY SymEntry;
|
||||
|
||||
while(!IsListEmpty(ListHead))
|
||||
{
|
||||
/* remove first entry */
|
||||
Entry = RemoveHeadList(ListHead);
|
||||
|
||||
/* fetch symbolic link entry */
|
||||
SymEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLIC_LINK_ENTRY, Entry);
|
||||
|
||||
/* free device interface string */
|
||||
RtlFreeUnicodeString(&SymEntry->SymbolicLink);
|
||||
/* free entry item */
|
||||
FreeItem(Entry);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspRegisterDeviceInterfaces(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN ULONG CategoriesCount,
|
||||
IN GUID const*Categories,
|
||||
IN PUNICODE_STRING ReferenceString,
|
||||
OUT PLIST_ENTRY SymbolicLinkList)
|
||||
{
|
||||
ULONG Index;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PSYMBOLIC_LINK_ENTRY SymEntry;
|
||||
|
||||
for(Index = 0; Index < CategoriesCount; Index++)
|
||||
{
|
||||
/* allocate a symbolic link entry */
|
||||
SymEntry = AllocateItem(NonPagedPool, sizeof(SYMBOLIC_LINK_ENTRY));
|
||||
/* check for success */
|
||||
if (!SymEntry)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* now register device interface */
|
||||
Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
|
||||
&Categories[Index],
|
||||
ReferenceString, /* see damn bug 4566 */
|
||||
&SymEntry->SymbolicLink);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to register device interface %x\n", Status);
|
||||
|
||||
/* free entry */
|
||||
FreeItem(SymEntry);
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
/* insert symbolic link entry */
|
||||
InsertTailList(SymbolicLinkList, &SymEntry->Entry);
|
||||
}
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +1,11 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/driver.c
|
||||
* PURPOSE: KS Driver functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
#include "ksfunc.h"
|
||||
|
@ -15,7 +23,7 @@ DriverEntry(
|
|||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
PKSDEVICE
|
||||
|
@ -23,23 +31,12 @@ NTAPI
|
|||
KsGetDeviceForDeviceObject(
|
||||
IN PDEVICE_OBJECT FunctionalDeviceObject)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsInitializeDevice(
|
||||
IN PDEVICE_OBJECT FunctionalDeviceObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDEVICE_OBJECT NextDeviceObject,
|
||||
IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
return &DeviceExtension->DeviceHeader->KsDevice;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -58,9 +55,8 @@ KsCreateDevice(
|
|||
NTSTATUS Status = STATUS_DEVICE_REMOVED;
|
||||
PDEVICE_OBJECT FunctionalDeviceObject= NULL;
|
||||
PDEVICE_OBJECT OldHighestDeviceObject;
|
||||
|
||||
if (!ExtensionSize)
|
||||
ExtensionSize = sizeof(PVOID);
|
||||
ExtensionSize = sizeof(KSDEVICE_HEADER);
|
||||
|
||||
Status = IoCreateDevice(DriverObject, ExtensionSize, NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -71,7 +67,12 @@ KsCreateDevice(
|
|||
{
|
||||
Status = KsInitializeDevice(FunctionalDeviceObject, PhysicalDeviceObject, OldHighestDeviceObject, Descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_DEVICE_REMOVED;
|
||||
}
|
||||
|
||||
/* check if all succeeded */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (OldHighestDeviceObject)
|
||||
|
@ -81,9 +82,20 @@ KsCreateDevice(
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* set device flags */
|
||||
FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
|
||||
FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
||||
|
||||
if (Device)
|
||||
{
|
||||
/* get PKSDEVICE struct */
|
||||
*Device = KsGetDeviceForDeviceObject(FunctionalDeviceObject);
|
||||
|
||||
if (ExtensionSize > sizeof(KSDEVICE_HEADER))
|
||||
{
|
||||
/* caller needs a device extension */
|
||||
(*Device)->Context = (PVOID)((ULONG_PTR)FunctionalDeviceObject->DeviceExtension + sizeof(KSDEVICE_HEADER));
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
@ -135,9 +147,13 @@ KsInitializeDriver(
|
|||
}
|
||||
}
|
||||
/* Setting our IRP handlers */
|
||||
//DriverObject->MajorFunction[IRP_MJ_CREATE] = KspDispatch;
|
||||
//DriverObject->MajorFunction[IRP_MJ_PNP] = KspDispatch;
|
||||
//DriverObject->MajorFunction[IRP_MJ_POWER] = KspDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = IKsDevice_Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = IKsDevice_Pnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = IKsDevice_Power;
|
||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
|
||||
|
||||
/* The driver unload routine */
|
||||
DriverObject->DriverUnload = KsNullDriverUnload;
|
||||
|
||||
/* The driver-supplied AddDevice */
|
||||
DriverObject->DriverExtension->AddDevice = KsAddDevice;
|
||||
|
|
|
@ -1,55 +1,20 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/event.c
|
||||
* PURPOSE: KS Event functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/* ===============================================================
|
||||
Event Functions
|
||||
*/
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsGenerateEvent(
|
||||
IN PKSEVENT_ENTRY EntryEvent)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsEnableEventWithAllocator(
|
||||
IN PIRP Irp,
|
||||
IN ULONG EventSetsCount,
|
||||
IN PKSEVENT_SET EventSet,
|
||||
IN OUT PLIST_ENTRY EventsList OPTIONAL,
|
||||
IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
|
||||
IN PVOID EventsLock OPTIONAL,
|
||||
IN PFNKSALLOCATOR Allocator OPTIONAL,
|
||||
IN ULONG EventItemSize OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsGenerateDataEvent(
|
||||
IN PKSEVENT_ENTRY EventEntry,
|
||||
IN ULONG DataSize,
|
||||
IN PVOID Data)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsEnableEvent(
|
||||
IN PIRP Irp,
|
||||
IN ULONG EventSetsCount,
|
||||
|
@ -65,17 +30,30 @@ KsEnableEvent(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsDiscardEvent(
|
||||
IN PKSEVENT_ENTRY EventEntry)
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsEnableEventWithAllocator(
|
||||
IN PIRP Irp,
|
||||
IN ULONG EventSetsCount,
|
||||
IN PKSEVENT_SET EventSet,
|
||||
IN OUT PLIST_ENTRY EventsList OPTIONAL,
|
||||
IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
|
||||
IN PVOID EventsLock OPTIONAL,
|
||||
IN PFNKSALLOCATOR Allocator OPTIONAL,
|
||||
IN ULONG EventItemSize OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsDisableEvent(
|
||||
IN PIRP Irp,
|
||||
IN OUT PLIST_ENTRY EventsList,
|
||||
|
@ -89,7 +67,22 @@ KsDisableEvent(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsDiscardEvent(
|
||||
IN PKSEVENT_ENTRY EventEntry)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsFreeEventList(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN OUT PLIST_ENTRY EventsList,
|
||||
|
@ -98,3 +91,46 @@ KsFreeEventList(
|
|||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGenerateEvent(
|
||||
IN PKSEVENT_ENTRY EntryEvent)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGenerateDataEvent(
|
||||
IN PKSEVENT_ENTRY EventEntry,
|
||||
IN ULONG DataSize,
|
||||
IN PVOID Data)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsGenerateEventList(
|
||||
IN GUID* Set OPTIONAL,
|
||||
IN ULONG EventId,
|
||||
IN PLIST_ENTRY EventsList,
|
||||
IN KSEVENTS_LOCKTYPE EventsFlags,
|
||||
IN PVOID EventsLock)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
917
reactos/drivers/ksfilter/ks/filter.c
Normal file
917
reactos/drivers/ksfilter/ks/filter.c
Normal file
|
@ -0,0 +1,917 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/filter.c
|
||||
* PURPOSE: KS IKsFilter interface functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IKsFilterVtbl *lpVtbl;
|
||||
IKsControlVtbl *lpVtblKsControl;
|
||||
IKsFilterFactory * FilterFactory;
|
||||
LONG ref;
|
||||
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
KSFILTER Filter;
|
||||
KSTOPOLOGY Topology;
|
||||
KSPIN_DESCRIPTOR * PinDescriptors;
|
||||
ULONG PinDescriptorCount;
|
||||
PKSFILTERFACTORY Factory;
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
|
||||
ULONG *PinInstanceCount;
|
||||
}IKsFilterImpl;
|
||||
|
||||
const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
|
||||
const GUID IID_IKsFilter = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
|
||||
const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
||||
const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
|
||||
|
||||
|
||||
DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, KspTopologyPropertyHandler);
|
||||
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, KspPinPropertyHandler, KspPinPropertyHandler, KspPinPropertyHandler);
|
||||
|
||||
KSPROPERTY_SET FilterPropertySet[] =
|
||||
{
|
||||
{
|
||||
&KSPROPSETID_Topology,
|
||||
sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
|
||||
(const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
&KSPROPSETID_Pin,
|
||||
sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
|
||||
(const KSPROPERTY_ITEM*)&IKsFilterPinSet,
|
||||
0,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsControl_fnQueryInterface(
|
||||
IKsControl * iface,
|
||||
IN REFIID refiid,
|
||||
OUT PVOID* Output)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||
{
|
||||
*Output = &This->lpVtbl;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsControl_fnAddRef(
|
||||
IKsControl * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsControl_fnRelease(
|
||||
IKsControl * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
InterlockedDecrement(&This->ref);
|
||||
|
||||
/* Return new reference count */
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsControl_fnKsProperty(
|
||||
IKsControl * iface,
|
||||
IN PKSPROPERTY Property,
|
||||
IN ULONG PropertyLength,
|
||||
IN OUT PVOID PropertyData,
|
||||
IN ULONG DataLength,
|
||||
OUT ULONG* BytesReturned)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsControl_fnKsMethod(
|
||||
IKsControl * iface,
|
||||
IN PKSMETHOD Method,
|
||||
IN ULONG MethodLength,
|
||||
IN OUT PVOID MethodData,
|
||||
IN ULONG DataLength,
|
||||
OUT ULONG* BytesReturned)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsControl_fnKsEvent(
|
||||
IKsControl * iface,
|
||||
IN PKSEVENT Event OPTIONAL,
|
||||
IN ULONG EventLength,
|
||||
IN OUT PVOID EventData,
|
||||
IN ULONG DataLength,
|
||||
OUT ULONG* BytesReturned)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
|
||||
|
||||
if (Event)
|
||||
{
|
||||
return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
|
||||
}
|
||||
else
|
||||
{
|
||||
return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static IKsControlVtbl vt_IKsControl =
|
||||
{
|
||||
IKsControl_fnQueryInterface,
|
||||
IKsControl_fnAddRef,
|
||||
IKsControl_fnRelease,
|
||||
IKsControl_fnKsProperty,
|
||||
IKsControl_fnKsMethod,
|
||||
IKsControl_fnKsEvent
|
||||
};
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnQueryInterface(
|
||||
IKsFilter * iface,
|
||||
IN REFIID refiid,
|
||||
OUT PVOID* Output)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
|
||||
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
|
||||
IsEqualGUIDAligned(refiid, &IID_IKsFilter))
|
||||
{
|
||||
*Output = &This->lpVtbl;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
|
||||
{
|
||||
*Output = &This->lpVtblKsControl;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsFilter_fnAddRef(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
|
||||
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsFilter_fnRelease(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
|
||||
|
||||
InterlockedDecrement(&This->ref);
|
||||
|
||||
if (This->ref == 0)
|
||||
{
|
||||
FreeItem(This);
|
||||
return 0;
|
||||
}
|
||||
/* Return new reference count */
|
||||
return This->ref;
|
||||
|
||||
}
|
||||
|
||||
PKSFILTER
|
||||
NTAPI
|
||||
IKsFilter_fnGetStruct(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
|
||||
|
||||
return &This->Filter;
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
IKsFilter_fnDoAllNecessaryPinsExist(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnCreateNode(
|
||||
IKsFilter * iface,
|
||||
IN PIRP Irp,
|
||||
IN IKsPin * Pin,
|
||||
IN PLIST_ENTRY ListEntry)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnBindProcessPinsToPipeSection(
|
||||
IKsFilter * iface,
|
||||
IN struct KSPROCESSPIPESECTION *Section,
|
||||
IN PVOID Create,
|
||||
IN PKSPIN KsPin,
|
||||
OUT IKsPin **Pin,
|
||||
OUT PKSGATE *OutGate)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnUnbindProcessPinsFromPipeSection(
|
||||
IKsFilter * iface,
|
||||
IN struct KSPROCESSPIPESECTION *Section)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnAddProcessPin(
|
||||
IKsFilter * iface,
|
||||
IN PKSPROCESSPIN ProcessPin)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_fnRemoveProcessPin(
|
||||
IKsFilter * iface,
|
||||
IN PKSPROCESSPIN ProcessPin)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
IKsFilter_fnReprepareProcessPipeSection(
|
||||
IKsFilter * iface,
|
||||
IN struct KSPROCESSPIPESECTION *PipeSection,
|
||||
IN PULONG Data)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsFilter_fnDeliverResetState(
|
||||
IKsFilter * iface,
|
||||
IN struct KSPROCESSPIPESECTION *PipeSection,
|
||||
IN KSRESET ResetState)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
IKsFilter_fnIsFrameHolding(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsFilter_fnRegisterForCopyCallbacks(
|
||||
IKsFilter * iface,
|
||||
IKsQueue *Queue,
|
||||
BOOL Register)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
PKSPROCESSPIN_INDEXENTRY
|
||||
NTAPI
|
||||
IKsFilter_fnGetProcessDispatch(
|
||||
IKsFilter * iface)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IKsFilterVtbl vt_IKsFilter =
|
||||
{
|
||||
IKsFilter_fnQueryInterface,
|
||||
IKsFilter_fnAddRef,
|
||||
IKsFilter_fnRelease,
|
||||
IKsFilter_fnGetStruct,
|
||||
IKsFilter_fnDoAllNecessaryPinsExist,
|
||||
IKsFilter_fnCreateNode,
|
||||
IKsFilter_fnBindProcessPinsToPipeSection,
|
||||
IKsFilter_fnUnbindProcessPinsFromPipeSection,
|
||||
IKsFilter_fnAddProcessPin,
|
||||
IKsFilter_fnRemoveProcessPin,
|
||||
IKsFilter_fnReprepareProcessPipeSection,
|
||||
IKsFilter_fnDeliverResetState,
|
||||
IKsFilter_fnIsFrameHolding,
|
||||
IKsFilter_fnRegisterForCopyCallbacks,
|
||||
IKsFilter_fnGetProcessDispatch
|
||||
};
|
||||
|
||||
NTSTATUS
|
||||
IKsFilter_GetFilterFromIrp(
|
||||
IN PIRP Irp,
|
||||
OUT IKsFilter **Filter)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* santiy check */
|
||||
ASSERT(IoStack->FileObject != NULL);
|
||||
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext;
|
||||
|
||||
/* sanity is important */
|
||||
ASSERT(ObjectHeader != NULL);
|
||||
ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
|
||||
ASSERT(ObjectHeader->Unknown != NULL);
|
||||
|
||||
/* get our private interface */
|
||||
Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* something is wrong here */
|
||||
DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
|
||||
Irp->IoStatus.Status = Status;
|
||||
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_DispatchClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
IKsFilter * Filter;
|
||||
IKsFilterImpl * This;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* obtain filter from object header */
|
||||
Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
/* get our real implementation */
|
||||
This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl);
|
||||
|
||||
/* does the driver support notifications */
|
||||
if (This->Factory->FilterDescriptor && This->Factory->FilterDescriptor->Dispatch && This->Factory->FilterDescriptor->Dispatch->Close)
|
||||
{
|
||||
/* call driver's filter close function */
|
||||
Status = This->Factory->FilterDescriptor->Dispatch->Close(&This->Filter, Irp);
|
||||
}
|
||||
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
/* save the result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
/* complete irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* remove our instance from the filter factory */
|
||||
This->FilterFactory->lpVtbl->RemoveFilterInstance(This->FilterFactory, Filter);
|
||||
|
||||
/* now release the acquired interface */
|
||||
Filter->lpVtbl->Release(Filter);
|
||||
|
||||
/* free object header */
|
||||
KsFreeObjectHeader(This->ObjectHeader);
|
||||
}
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspHandlePropertyInstances(
|
||||
IN PIO_STATUS_BLOCK IoStatus,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data,
|
||||
IN IKsFilterImpl * This,
|
||||
IN BOOL Global)
|
||||
{
|
||||
KSPIN_CINSTANCES * Instances;
|
||||
KSP_PIN * Pin = (KSP_PIN*)Request;
|
||||
|
||||
if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
|
||||
{
|
||||
/* no filter / pin descriptor */
|
||||
IoStatus->Status = STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* ignore custom structs for now */
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
|
||||
|
||||
Instances = (KSPIN_CINSTANCES*)Data;
|
||||
/* max instance count */
|
||||
Instances->PossibleCount = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible;
|
||||
/* current instance count */
|
||||
Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
|
||||
|
||||
IoStatus->Information = sizeof(KSPIN_CINSTANCES);
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspHandleNecessaryPropertyInstances(
|
||||
IN PIO_STATUS_BLOCK IoStatus,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data,
|
||||
IN IKsFilterImpl * This)
|
||||
{
|
||||
PULONG Result;
|
||||
KSP_PIN * Pin = (KSP_PIN*)Request;
|
||||
|
||||
if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
|
||||
{
|
||||
/* no filter / pin descriptor */
|
||||
IoStatus->Status = STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* ignore custom structs for now */
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
|
||||
|
||||
Result = (PULONG)Data;
|
||||
*Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
|
||||
|
||||
IoStatus->Information = sizeof(ULONG);
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KspHandleDataIntersection(
|
||||
IN PIRP Irp,
|
||||
IN PIO_STATUS_BLOCK IoStatus,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data,
|
||||
IN ULONG DataLength,
|
||||
IN IKsFilterImpl * This)
|
||||
{
|
||||
PKSMULTIPLE_ITEM MultipleItem;
|
||||
PKSDATARANGE DataRange;
|
||||
NTSTATUS Status = STATUS_NO_MATCH;
|
||||
ULONG Index, Length;
|
||||
KSP_PIN * Pin = (KSP_PIN*)Request;
|
||||
|
||||
/* Access parameters */
|
||||
MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
|
||||
DataRange = (PKSDATARANGE)(MultipleItem + 1);
|
||||
|
||||
if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
|
||||
{
|
||||
/* no filter / pin descriptor */
|
||||
IoStatus->Status = STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* ignore custom structs for now */
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
|
||||
ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
|
||||
|
||||
if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
|
||||
This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
|
||||
This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
|
||||
{
|
||||
/* no driver supported intersect handler / no provided data ranges */
|
||||
IoStatus->Status = STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
for(Index = 0; Index < MultipleItem->Count; Index++)
|
||||
{
|
||||
/* Call miniport's properitary handler */
|
||||
Status = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler(NULL, /* context */
|
||||
Irp,
|
||||
Pin,
|
||||
DataRange,
|
||||
(PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges,
|
||||
DataLength,
|
||||
Data,
|
||||
&Length);
|
||||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
IoStatus->Information = Length;
|
||||
break;
|
||||
}
|
||||
DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
|
||||
}
|
||||
|
||||
IoStatus->Status = Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspPinPropertyHandler(
|
||||
IN PIRP Irp,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
IKsFilterImpl * This;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* get filter implementation */
|
||||
This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch(Request->Id)
|
||||
{
|
||||
case KSPROPERTY_PIN_CTYPES:
|
||||
case KSPROPERTY_PIN_DATAFLOW:
|
||||
case KSPROPERTY_PIN_DATARANGES:
|
||||
case KSPROPERTY_PIN_INTERFACES:
|
||||
case KSPROPERTY_PIN_MEDIUMS:
|
||||
case KSPROPERTY_PIN_COMMUNICATION:
|
||||
case KSPROPERTY_PIN_CATEGORY:
|
||||
case KSPROPERTY_PIN_NAME:
|
||||
case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
|
||||
Status = KsPinPropertyHandler(Irp, Request, Data, This->PinDescriptorCount, This->PinDescriptors);
|
||||
break;
|
||||
case KSPROPERTY_PIN_GLOBALCINSTANCES:
|
||||
Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
|
||||
break;
|
||||
case KSPROPERTY_PIN_CINSTANCES:
|
||||
Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
|
||||
break;
|
||||
case KSPROPERTY_PIN_NECESSARYINSTANCES:
|
||||
Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
|
||||
break;
|
||||
|
||||
case KSPROPERTY_PIN_DATAINTERSECTION:
|
||||
Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
|
||||
break;
|
||||
case KSPROPERTY_PIN_PHYSICALCONNECTION:
|
||||
case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
|
||||
UNIMPLEMENTED
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FindPropertyHandler(
|
||||
IN PIO_STATUS_BLOCK IoStatus,
|
||||
IN KSPROPERTY_SET * FilterPropertySet,
|
||||
IN ULONG FilterPropertySetCount,
|
||||
IN PKSPROPERTY Property,
|
||||
IN ULONG InputBufferLength,
|
||||
IN ULONG OutputBufferLength,
|
||||
OUT PFNKSHANDLER *PropertyHandler)
|
||||
{
|
||||
ULONG Index, ItemIndex;
|
||||
|
||||
for(Index = 0; Index < FilterPropertySetCount; Index++)
|
||||
{
|
||||
if (IsEqualGUIDAligned(&Property->Set, FilterPropertySet[Index].Set))
|
||||
{
|
||||
for(ItemIndex = 0; ItemIndex < FilterPropertySet[Index].PropertiesCount; ItemIndex++)
|
||||
{
|
||||
if (FilterPropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
|
||||
{
|
||||
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
||||
*PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
|
||||
|
||||
if (Property->Flags & KSPROPERTY_TYPE_GET)
|
||||
*PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
|
||||
|
||||
if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
|
||||
{
|
||||
/* too small input buffer */
|
||||
IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty;
|
||||
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
|
||||
{
|
||||
/* too small output buffer */
|
||||
IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinData;
|
||||
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilter_DispatchDeviceIoControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PFNKSHANDLER PropertyHandler = NULL;
|
||||
IKsFilter * Filter;
|
||||
IKsFilterImpl * This;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* obtain filter from object header */
|
||||
Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
/* get our real implementation */
|
||||
This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl);
|
||||
|
||||
/* current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
||||
/* release filter interface */
|
||||
Filter->lpVtbl->Release(Filter);
|
||||
|
||||
/* complete and forget irp */
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* find a supported property handler */
|
||||
Status = FindPropertyHandler(&Irp->IoStatus, FilterPropertySet, 2, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)This;
|
||||
DPRINT("Calling property handler %p\n", PropertyHandler);
|
||||
Status = PropertyHandler(Irp, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, Irp->UserBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* call driver's property handler */
|
||||
UNIMPLEMENTED
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
static KSDISPATCH_TABLE DispatchTable =
|
||||
{
|
||||
IKsFilter_DispatchDeviceIoControl,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
IKsFilter_DispatchClose,
|
||||
KsDispatchQuerySecurity,
|
||||
KsDispatchSetSecurity,
|
||||
KsDispatchFastIoDeviceControlFailure,
|
||||
KsDispatchFastReadFailure,
|
||||
KsDispatchFastReadFailure,
|
||||
};
|
||||
|
||||
|
||||
NTSTATUS
|
||||
IKsFilter_CreateDescriptors(
|
||||
IKsFilterImpl * This,
|
||||
KSFILTER_DESCRIPTOR* FilterDescriptor)
|
||||
{
|
||||
ULONG Index = 0;
|
||||
|
||||
/* initialize pin descriptors */
|
||||
if (FilterDescriptor->PinDescriptorsCount)
|
||||
{
|
||||
/* allocate pin instance count array */
|
||||
This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount);
|
||||
if(!This->PinDescriptors)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
||||
/* allocate pin descriptor array */
|
||||
This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount);
|
||||
if(!This->PinDescriptors)
|
||||
{
|
||||
FreeItem(This->PinInstanceCount);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* set pin count */
|
||||
This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
|
||||
/* now copy those pin descriptors over */
|
||||
for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
|
||||
{
|
||||
/* copy one pin per time */
|
||||
RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize topology descriptor */
|
||||
This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
|
||||
This->Topology.Categories = FilterDescriptor->Categories;
|
||||
This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
|
||||
This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
|
||||
This->Topology.TopologyConnections = FilterDescriptor->Connections;
|
||||
|
||||
if (This->Topology.TopologyNodesCount > 0)
|
||||
{
|
||||
This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
|
||||
/* allocate topology node types array */
|
||||
if (!This->Topology.TopologyNodes)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
|
||||
/* allocate topology names array */
|
||||
if (!This->Topology.TopologyNodesNames)
|
||||
{
|
||||
FreeItem((PVOID)This->Topology.TopologyNodes);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
for(Index = 0; Index < This->Topology.TopologyNodesCount; Index++)
|
||||
{
|
||||
/* copy topology type */
|
||||
RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
|
||||
/* copy topology name */
|
||||
RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
|
||||
}
|
||||
}
|
||||
|
||||
/* done! */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateFilter(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN IKsFilterFactory *iface)
|
||||
{
|
||||
IKsFilterImpl * This;
|
||||
PKSFILTERFACTORY Factory;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
/* get the filter factory */
|
||||
Factory = iface->lpVtbl->GetStruct(iface);
|
||||
|
||||
if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
|
||||
{
|
||||
/* Sorry it just will not work */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* allocate filter instance */
|
||||
This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory));
|
||||
if (!This)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* get current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* initialize filter instance */
|
||||
This->ref = 1;
|
||||
This->lpVtbl = &vt_IKsFilter;
|
||||
This->lpVtblKsControl = &vt_IKsControl;
|
||||
This->Filter.Descriptor = Factory->FilterDescriptor;
|
||||
This->Factory = Factory;
|
||||
This->FilterFactory = iface;
|
||||
This->FileObject = IoStack->FileObject;
|
||||
|
||||
/* allocate the stream descriptors */
|
||||
Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* what can go wrong, goes wrong */
|
||||
FreeItem(This);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now add the filter instance to the filter factory */
|
||||
Status = iface->lpVtbl->AddFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to add filter */
|
||||
FreeItem(This);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now let driver initialize the filter instance */
|
||||
Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
|
||||
{
|
||||
/* driver failed to initialize */
|
||||
DPRINT1("Driver: Status %x\n", Status);
|
||||
|
||||
/* remove filter instance from filter factory */
|
||||
iface->lpVtbl->RemoveFilterInstance(iface, (IKsFilter*)&This->lpVtbl);
|
||||
|
||||
/* free filter instance */
|
||||
FreeItem(This);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now allocate the object header */
|
||||
Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 0, NULL, Irp, &DispatchTable);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to allocate object header */
|
||||
DPRINT1("Failed to allocate object header %x\n", Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* initialize object header */
|
||||
This->ObjectHeader->Type = KsObjectTypeFilter;
|
||||
This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
|
||||
|
||||
|
||||
/* completed initialization */
|
||||
return Status;
|
||||
}
|
471
reactos/drivers/ksfilter/ks/filterfactory.c
Normal file
471
reactos/drivers/ksfilter/ks/filterfactory.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/filterfactory.c
|
||||
* PURPOSE: KS IKsFilterFactory interface functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IKsFilterFactoryVtbl *lpVtbl;
|
||||
KSFILTERFACTORY FilterFactory;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
|
||||
LONG ref;
|
||||
|
||||
PFNKSFILTERFACTORYPOWER SleepCallback;
|
||||
PFNKSFILTERFACTORYPOWER WakeCallback;
|
||||
|
||||
LIST_ENTRY SymbolicLinkList;
|
||||
LIST_ENTRY FilterInstanceList;
|
||||
|
||||
|
||||
}IKsFilterFactoryImpl;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
IKsFilter *FilterInstance;
|
||||
}FILTER_INSTANCE_ENTRY, *PFILTER_INSTANCE_ENTRY;
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsFilterFactory_ItemFreeCb(
|
||||
IN PKSOBJECT_CREATE_ITEM CreateItem)
|
||||
{
|
||||
/* callback when create item is freed in the device header */
|
||||
IKsFilterFactory * iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
|
||||
|
||||
iface->lpVtbl->Release(iface);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_Create(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
IKsFilterFactory * iface;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* access the create item */
|
||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||
if (!CreateItem)
|
||||
{
|
||||
DPRINT1("IKsFilterFactory_Create no CreateItem\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* get filter factory interface */
|
||||
iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
|
||||
|
||||
/* create a filter instance */
|
||||
Status = KspCreateFilter(DeviceObject, Irp, iface);
|
||||
|
||||
DPRINT("KspCreateFilter Status %x\n", Status);
|
||||
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_fnQueryInterface(
|
||||
IKsFilterFactory * iface,
|
||||
IN REFIID refiid,
|
||||
OUT PVOID* Output)
|
||||
{
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||
{
|
||||
*Output = &This->lpVtbl;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsFilterFactory_fnAddRef(
|
||||
IKsFilterFactory * iface)
|
||||
{
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsFilterFactory_fnRelease(
|
||||
IKsFilterFactory * iface)
|
||||
{
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
InterlockedDecrement(&This->ref);
|
||||
|
||||
if (This->ref == 0)
|
||||
{
|
||||
if (!IsListEmpty(&This->SymbolicLinkList))
|
||||
{
|
||||
/* disable device interfaces */
|
||||
KspSetDeviceInterfacesState(&This->SymbolicLinkList, FALSE);
|
||||
/* free device interface strings */
|
||||
KspFreeDeviceInterfaces(&This->SymbolicLinkList);
|
||||
}
|
||||
|
||||
FreeItem(This);
|
||||
return 0;
|
||||
}
|
||||
/* Return new reference count */
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
KSFILTERFACTORY*
|
||||
NTAPI
|
||||
IKsFilterFactory_fnGetStruct(
|
||||
IKsFilterFactory * iface)
|
||||
{
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
return &This->FilterFactory;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_fnSetDeviceClassesState(
|
||||
IKsFilterFactory * iface,
|
||||
IN BOOLEAN Enable)
|
||||
{
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
return KspSetDeviceInterfacesState(&This->SymbolicLinkList, Enable);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_fnInitialize(
|
||||
IKsFilterFactory * iface,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN const KSFILTER_DESCRIPTOR *Descriptor,
|
||||
IN PWSTR RefString OPTIONAL,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags,
|
||||
IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
|
||||
IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
|
||||
OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
|
||||
{
|
||||
UNICODE_STRING ReferenceString;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
KSOBJECT_CREATE_ITEM CreateItem;
|
||||
BOOL FreeString = FALSE;
|
||||
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
/* initialize filterfactory */
|
||||
This->SleepCallback = SleepCallback;
|
||||
This->WakeCallback = WakeCallback;
|
||||
This->FilterFactory.FilterDescriptor = Descriptor;
|
||||
InitializeListHead(&This->SymbolicLinkList);
|
||||
InitializeListHead(&This->FilterInstanceList);
|
||||
|
||||
/* does the device use a reference string */
|
||||
if (RefString || !Descriptor->ReferenceGuid)
|
||||
{
|
||||
/* use device reference string */
|
||||
RtlInitUnicodeString(&ReferenceString, RefString);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create reference string from descriptor guid */
|
||||
Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* omg, we failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
FreeString = TRUE;
|
||||
}
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* now register the device interface */
|
||||
Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
|
||||
Descriptor->CategoriesCount,
|
||||
Descriptor->Categories,
|
||||
&ReferenceString,
|
||||
&This->SymbolicLinkList);
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
|
||||
|
||||
if (FreeString)
|
||||
{
|
||||
/* free unicode string */
|
||||
RtlFreeUnicodeString(&ReferenceString);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now setup the create item */
|
||||
CreateItem.SecurityDescriptor = SecurityDescriptor;
|
||||
CreateItem.Flags = CreateItemFlags;
|
||||
CreateItem.Create = IKsFilterFactory_Create;
|
||||
CreateItem.Context = (PVOID)&This->FilterFactory;
|
||||
RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
|
||||
|
||||
/* insert create item to device header */
|
||||
Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
|
||||
|
||||
if (FreeString)
|
||||
{
|
||||
/* free unicode string */
|
||||
RtlFreeUnicodeString(&ReferenceString);
|
||||
}
|
||||
|
||||
if (FilterFactory)
|
||||
{
|
||||
/* return filterfactory */
|
||||
*FilterFactory = &This->FilterFactory;
|
||||
|
||||
/*FIXME create object bag */
|
||||
}
|
||||
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_fnAddFilterInstance(
|
||||
IKsFilterFactory * iface,
|
||||
IN IKsFilter *FilterInstance)
|
||||
{
|
||||
PFILTER_INSTANCE_ENTRY Entry;
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
/* allocate filter instance entry */
|
||||
Entry = AllocateItem(NonPagedPool, sizeof(FILTER_INSTANCE_ENTRY));
|
||||
if (!Entry)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* initialize filter instance entry */
|
||||
Entry->FilterInstance = FilterInstance;
|
||||
|
||||
/* insert entry */
|
||||
InsertTailList(&This->FilterInstanceList, &Entry->Entry);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsFilterFactory_fnRemoveFilterInstance(
|
||||
IKsFilterFactory * iface,
|
||||
IN IKsFilter *FilterInstance)
|
||||
{
|
||||
PFILTER_INSTANCE_ENTRY InstanceEntry;
|
||||
PLIST_ENTRY Entry;
|
||||
IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
|
||||
|
||||
/* point to first entry */
|
||||
Entry = This->FilterInstanceList.Flink;
|
||||
|
||||
while(Entry != &This->FilterInstanceList)
|
||||
{
|
||||
InstanceEntry = (PFILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, FILTER_INSTANCE_ENTRY, Entry);
|
||||
if (InstanceEntry->FilterInstance == FilterInstance)
|
||||
{
|
||||
/* found entry */
|
||||
RemoveEntryList(&InstanceEntry->Entry);
|
||||
FreeItem(InstanceEntry);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* entry not in list! */
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl =
|
||||
{
|
||||
IKsFilterFactory_fnQueryInterface,
|
||||
IKsFilterFactory_fnAddRef,
|
||||
IKsFilterFactory_fnRelease,
|
||||
IKsFilterFactory_fnGetStruct,
|
||||
IKsFilterFactory_fnSetDeviceClassesState,
|
||||
IKsFilterFactory_fnInitialize,
|
||||
IKsFilterFactory_fnAddFilterInstance,
|
||||
IKsFilterFactory_fnRemoveFilterInstance
|
||||
};
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateFilterFactory(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN const KSFILTER_DESCRIPTOR *Descriptor,
|
||||
IN PWSTR RefString OPTIONAL,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags,
|
||||
IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
|
||||
IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
|
||||
OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
|
||||
{
|
||||
IKsFilterFactoryImpl * This;
|
||||
IKsFilterFactory * Filter;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Lets allocate a filterfactory */
|
||||
This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
|
||||
if (!This)
|
||||
{
|
||||
/* not enough memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* initialize struct */
|
||||
This->ref = 1;
|
||||
This->lpVtbl = &vt_IKsFilterFactoryVtbl;
|
||||
|
||||
/* map to com object */
|
||||
Filter = (IKsFilterFactory*)&This->lpVtbl;
|
||||
|
||||
/* initialize filter */
|
||||
Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
|
||||
/* did we succeed */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* destroy filterfactory */
|
||||
Filter->lpVtbl->Release(Filter);
|
||||
}
|
||||
|
||||
/* return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsCreateFilterFactory(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN const KSFILTER_DESCRIPTOR *Descriptor,
|
||||
IN PWSTR RefString OPTIONAL,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags,
|
||||
IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
|
||||
IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
|
||||
OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
|
||||
{
|
||||
return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsFilterFactorySetDeviceClassesState(
|
||||
IN PKSFILTERFACTORY FilterFactory,
|
||||
IN BOOLEAN NewState)
|
||||
{
|
||||
IKsFilterFactory * Factory = (IKsFilterFactory*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
|
||||
|
||||
return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
PUNICODE_STRING
|
||||
NTAPI
|
||||
KsFilterFactoryGetSymbolicLink(
|
||||
IN PKSFILTERFACTORY FilterFactory)
|
||||
{
|
||||
PSYMBOLIC_LINK_ENTRY LinkEntry;
|
||||
IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
|
||||
|
||||
if (IsListEmpty(&Factory->SymbolicLinkList))
|
||||
{
|
||||
/* device has not registered any interfaces */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get first entry */
|
||||
LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
|
||||
|
||||
/* return first link */
|
||||
return &LinkEntry->SymbolicLink;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsFilterFactoryAddCreateItem(
|
||||
IN PKSFILTERFACTORY FilterFactory,
|
||||
IN PWSTR RefString,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags)
|
||||
{
|
||||
KSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
|
||||
|
||||
/* initialize create item */
|
||||
CreateItem.Context = (PVOID)&Factory->FilterFactory;
|
||||
CreateItem.Create = IKsFilterFactory_Create;
|
||||
CreateItem.Flags = CreateItemFlags;
|
||||
CreateItem.SecurityDescriptor = SecurityDescriptor;
|
||||
RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
|
||||
|
||||
/* insert create item to device header */
|
||||
return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsFilterFactoryUpdateCacheData (
|
||||
IN PKSFILTERFACTORY FilterFactory,
|
||||
IN const KSFILTER_DESCRIPTOR* FilterDescriptor OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
116
reactos/drivers/ksfilter/ks/image.c
Normal file
116
reactos/drivers/ksfilter/ks/image.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsLoadResource(
|
||||
IN PVOID ImageBase,
|
||||
IN POOL_TYPE PoolType,
|
||||
IN ULONG_PTR ResourceName,
|
||||
IN ULONG ResourceType,
|
||||
OUT PVOID* Resource,
|
||||
OUT PULONG ResourceSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
LDR_RESOURCE_INFO ResourceInfo;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
|
||||
PVOID Data;
|
||||
ULONG Size;
|
||||
PVOID Result = NULL;
|
||||
|
||||
/* set up resource info */
|
||||
ResourceInfo.Type = ResourceType;
|
||||
ResourceInfo.Name = ResourceName;
|
||||
ResourceInfo.Language = 0;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* find the resource */
|
||||
Status = LdrFindResource_U(ImageBase, &ResourceInfo, RESOURCE_DATA_LEVEL, &ResourceDataEntry);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* try accessing it */
|
||||
Status = LdrAccessResource(ImageBase, ResourceDataEntry, &Data, &Size);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* allocate resource buffer */
|
||||
Result = ExAllocatePool(PoolType, Size);
|
||||
if (Result)
|
||||
{
|
||||
/* copy resource */
|
||||
RtlMoveMemory(Result, Data, Size);
|
||||
/* store result */
|
||||
*Resource = Result;
|
||||
*ResourceSize = Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not enough memory */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Exception, get the error code */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
if (Result)
|
||||
{
|
||||
/* free resource buffer in case of a failure */
|
||||
ExFreePool(Result);
|
||||
}
|
||||
}
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGetImageNameAndResourceId(
|
||||
IN HANDLE RegKey,
|
||||
OUT PUNICODE_STRING ImageName,
|
||||
OUT PULONG_PTR ResourceId,
|
||||
OUT PULONG ValueType)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsMapModuleName(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PUNICODE_STRING ModuleName,
|
||||
OUT PUNICODE_STRING ImageName,
|
||||
OUT PULONG_PTR ResourceId,
|
||||
OUT PULONG ValueType)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,11 @@
|
|||
/* ===============================================================
|
||||
Kernel-mode COM
|
||||
*/
|
||||
/*
|
||||
* 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
|
||||
Andrew Greenwood
|
||||
*/
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
|
|
|
@ -7,20 +7,26 @@
|
|||
<importlibrary definition="ks.spec" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>pseh</library>
|
||||
<define name="BUILDING_KS" />
|
||||
<define name="_COMDDK_" />
|
||||
<file>ks.rc</file>
|
||||
<file>api.c</file>
|
||||
<file>allocators.c</file>
|
||||
<file>bag.c</file>
|
||||
<file>device.c</file>
|
||||
<file>deviceinterface.c</file>
|
||||
<file>driver.c</file>
|
||||
<file>clocks.c</file>
|
||||
<file>connectivity.c</file>
|
||||
<file>events.c</file>
|
||||
<file>event.c</file>
|
||||
<file>filter.c</file>
|
||||
<file>filterfactory.c</file>
|
||||
<file>image.c</file>
|
||||
<file>irp.c</file>
|
||||
<file>methods.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>properties.c</file>
|
||||
<file>property.c</file>
|
||||
<file>topology.c</file>
|
||||
<file>worker.c</file>
|
||||
<file>kcom.c</file>
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
|
||||
#include "ksiface.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NewIKsDevice(IKsDevice** OutDevice);
|
||||
|
||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||
#define TAG_KSDEVICE TAG('K', 'S', 'E', 'D')
|
||||
#define TAG_KSOBJECT_TAG TAG('K', 'S', 'O', 'H')
|
||||
|
@ -21,6 +17,86 @@ KspCreateObjectType(
|
|||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE NodeHandle);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateFilterFactory(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN const KSFILTER_DESCRIPTOR *Descriptor,
|
||||
IN PWSTR RefString OPTIONAL,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags,
|
||||
IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
|
||||
IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
|
||||
OUT PKSFILTERFACTORY *FilterFactory OPTIONAL);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Create(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Pnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsDevice_Power(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateFilter(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN IKsFilterFactory *iface);
|
||||
|
||||
NTSTATUS
|
||||
KspSetDeviceInterfacesState(
|
||||
IN PLIST_ENTRY ListHead,
|
||||
IN BOOL Enable);
|
||||
|
||||
NTSTATUS
|
||||
KspFreeDeviceInterfaces(
|
||||
IN PLIST_ENTRY ListHead);
|
||||
|
||||
NTSTATUS
|
||||
KspRegisterDeviceInterfaces(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN ULONG CategoriesCount,
|
||||
IN GUID const*Categories,
|
||||
IN PUNICODE_STRING ReferenceString,
|
||||
OUT PLIST_ENTRY SymbolicLinkList);
|
||||
|
||||
NTSTATUS
|
||||
KspForwardIrpSynchronous(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
PVOID
|
||||
AllocateItem(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes);
|
||||
|
||||
VOID
|
||||
FreeItem(
|
||||
IN PVOID Item);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspTopologyPropertyHandler(
|
||||
IN PIRP Irp,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspPinPropertyHandler(
|
||||
IN PIRP Irp,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,129 @@
|
|||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsAllocator
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsAllocator
|
||||
|
||||
DECLARE_INTERFACE_(IKsAllocator, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
||||
STDMETHOD_(NTSTATUS, DispatchDeviceIoControl)(THIS_
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, Close)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, AllocateFrame)(THIS_
|
||||
IN PVOID * OutFrame) PURE;
|
||||
|
||||
STDMETHOD_(VOID, FreeFrame)(THIS_
|
||||
IN PVOID OutFrame) PURE;
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsPin
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsClock
|
||||
|
||||
DECLARE_INTERFACE_(IKsClock, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsPin
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsPin
|
||||
|
||||
DECLARE_INTERFACE_(IKsPin, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsQueue
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsQueue
|
||||
|
||||
DECLARE_INTERFACE_(IKsQueue, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsFilterFactory
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsFilter
|
||||
|
||||
struct KSPROCESSPIPESECTION;
|
||||
|
||||
|
||||
DECLARE_INTERFACE_(IKsFilter, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
||||
STDMETHOD_(PKSFILTER, GetStruct)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(BOOL, DoAllNecessaryPinsExist)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, CreateNode)(THIS_
|
||||
IN PIRP Irp,
|
||||
IN IKsPin * Pin,
|
||||
IN PLIST_ENTRY ListEntry) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, BindProcessPinsToPipeSection)(THIS_
|
||||
IN struct KSPROCESSPIPESECTION *Section,
|
||||
IN PVOID Create,
|
||||
IN PKSPIN KsPin,
|
||||
OUT IKsPin **Pin,
|
||||
OUT PKSGATE *OutGate) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, UnbindProcessPinsFromPipeSection)(THIS_
|
||||
IN struct KSPROCESSPIPESECTION *Section) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, AddProcessPin)(THIS_
|
||||
IN PKSPROCESSPIN ProcessPin) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, RemoveProcessPin)(THIS_
|
||||
IN PKSPROCESSPIN ProcessPin) PURE;
|
||||
|
||||
STDMETHOD_(BOOL, ReprepareProcessPipeSection)(THIS_
|
||||
IN struct KSPROCESSPIPESECTION *PipeSection,
|
||||
IN PULONG Data) PURE;
|
||||
|
||||
STDMETHOD_(VOID, DeliverResetState)(THIS_
|
||||
IN struct KSPROCESSPIPESECTION *PipeSection,
|
||||
IN KSRESET ResetState) PURE;
|
||||
|
||||
STDMETHOD_(BOOL, IsFrameHolding)(THIS);
|
||||
|
||||
STDMETHOD_(VOID, RegisterForCopyCallbacks)(THIS_
|
||||
IKsQueue * Queue,
|
||||
IN BOOL Enable) PURE;
|
||||
|
||||
STDMETHOD_(PKSPROCESSPIN_INDEXENTRY, GetProcessDispatch)(THIS);
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsFilterFactory
|
||||
*****************************************************************************
|
||||
|
@ -26,10 +149,26 @@ DECLARE_INTERFACE_(IKsFilterFactory, IUnknown)
|
|||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
||||
STDMETHOD_(KSFILTERFACTORY*,GetStruct)(THIS) PURE;
|
||||
STDMETHOD_(KSFILTERFACTORY*, GetStruct)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS,SetDeviceClassesState)(THIS_
|
||||
STDMETHOD_(NTSTATUS, SetDeviceClassesState)(THIS_
|
||||
IN BOOLEAN Enable)PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, Initialize)(THIS_
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN const KSFILTER_DESCRIPTOR *Descriptor,
|
||||
IN PWSTR RefString OPTIONAL,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN ULONG CreateItemFlags,
|
||||
IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
|
||||
IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
|
||||
OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, AddFilterInstance)(THIS_
|
||||
IN IKsFilter *Filter)PURE;
|
||||
|
||||
STDMETHOD_(NTSTATUS, RemoveFilterInstance)(THIS_
|
||||
IN IKsFilter *Filter)PURE;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,33 +1,60 @@
|
|||
#ifndef KSTYPES_H__
|
||||
#define KSTYPES_H__
|
||||
|
||||
struct KSIDEVICE_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
KSDISPATCH_TABLE DispatchTable;
|
||||
KSOBJECTTYPE Type;
|
||||
ULONG ItemCount;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
UNICODE_STRING ObjectClass;
|
||||
PUNKNOWN Unknown;
|
||||
|
||||
PDEVICE_OBJECT TargetDevice;
|
||||
LIST_ENTRY TargetDeviceListEntry;
|
||||
|
||||
PDEVICE_OBJECT ParentDeviceObject;
|
||||
|
||||
PFNKSCONTEXT_DISPATCH PowerDispatch;
|
||||
PVOID PowerContext;
|
||||
LIST_ENTRY PowerDispatchEntry;
|
||||
|
||||
}KSIOBJECT_HEADER, *PKSIOBJECT_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
PFNKSITEMFREECALLBACK ItemFreeCallback;
|
||||
LONG ReferenceCount;
|
||||
}DEVICE_ITEM, *PDEVICE_ITEM;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IKsDeviceVtbl *lpVtblIKsDevice;
|
||||
LONG ref;
|
||||
ERESOURCE SecurityLock;
|
||||
|
||||
USHORT MaxItems;
|
||||
DEVICE_ITEM *ItemList;
|
||||
|
||||
ULONG DeviceIndex;
|
||||
KSPIN_LOCK ItemListLock;
|
||||
|
||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
||||
PDEVICE_OBJECT NextDeviceObject;
|
||||
ERESOURCE SecurityLock;
|
||||
|
||||
KSTARGET_STATE TargetState;
|
||||
LIST_ENTRY TargetDeviceList;
|
||||
|
||||
KSDEVICE KsDevice;
|
||||
KMUTEX DeviceMutex;
|
||||
KSDEVICE_DESCRIPTOR* Descriptor;
|
||||
|
||||
LIST_ENTRY PowerDispatchList;
|
||||
|
||||
}KSIDEVICE_HEADER, *PKSIDEVICE_HEADER;
|
||||
|
||||
|
||||
|
@ -43,5 +70,17 @@ typedef struct
|
|||
PIRP Irp;
|
||||
}QUEUE_ENTRY, *PQUEUE_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
UNICODE_STRING SymbolicLink;
|
||||
}SYMBOLIC_LINK_ENTRY, *PSYMBOLIC_LINK_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
PIO_WORKITEM WorkItem;
|
||||
}PNP_POSTSTART_CONTEXT, *PPNP_POSTSTART_CONTEXT;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
#include "priv.h"
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/methods.c
|
||||
* PURPOSE: KS Allocator functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
/* ===============================================================
|
||||
Method Functions
|
||||
*/
|
||||
#include "priv.h"
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsMethodHandler(
|
||||
IN PIRP Irp,
|
||||
IN ULONG MethodSetsCount,
|
||||
|
@ -20,7 +26,9 @@ KsMethodHandler(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsMethodHandlerWithAllocator(
|
||||
IN PIRP Irp,
|
||||
IN ULONG MethodSetsCount,
|
||||
|
@ -35,7 +43,9 @@ KsMethodHandlerWithAllocator(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI BOOLEAN NTAPI
|
||||
KSDDKAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KsFastMethodHandler(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PKSMETHOD UNALIGNED Method,
|
||||
|
|
|
@ -1,175 +1,84 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/misc.c
|
||||
* PURPOSE: KS Allocator functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/* ===============================================================
|
||||
Misc. Helper Functions
|
||||
*/
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsCacheMedium(
|
||||
IN PUNICODE_STRING SymbolicLink,
|
||||
IN PKSPIN_MEDIUM Medium,
|
||||
IN ULONG PinDirection)
|
||||
PVOID
|
||||
AllocateItem(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
PVOID Item = ExAllocatePool(PoolType, NumberOfBytes);
|
||||
if (!Item)
|
||||
return Item;
|
||||
|
||||
RtlZeroMemory(Item, NumberOfBytes);
|
||||
return Item;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsDefaultDispatchPnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
VOID
|
||||
FreeItem(
|
||||
IN PVOID Item)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
ExFreePool(Item);
|
||||
}
|
||||
|
||||
DPRINT1("KsDefaultDispatchPnp entered with func %x\n", IoStack->MinorFunction);
|
||||
|
||||
switch(IoStack->MinorFunction)
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspForwardIrpSynchronousCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
if (Irp->PendingReturned == TRUE)
|
||||
{
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
// FIXME
|
||||
// destroy device header, detach device and delete device
|
||||
case IRP_MN_START_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
default:
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
//Status = IoCallDriver(NULL /* PnpBaseObject */, Irp);
|
||||
KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
return Status;
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsSetDevicePnpAndBaseObject(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PDEVICE_OBJECT PnpDeviceObject,
|
||||
IN PDEVICE_OBJECT BaseDevice)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsDefaultDispatchPower(
|
||||
NTSTATUS
|
||||
KspForwardIrpSynchronous(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PKSIDEVICE_HEADER DeviceHeader;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsSetPowerDispatch(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
|
||||
IN PVOID PowerContext OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsReferenceBusObject(
|
||||
IN KSDEVICE_HEADER Header)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
/* initialize the notification event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsDereferenceBusObject(
|
||||
IN KSDEVICE_HEADER Header)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsFreeObjectCreateItem(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PUNICODE_STRING CreateItem)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
IoSetCompletionRoutine(Irp, KspForwardIrpSynchronousCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsFreeObjectCreateItemsByContext(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN PVOID Context)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsLoadResource(
|
||||
IN PVOID ImageBase,
|
||||
IN POOL_TYPE PoolType,
|
||||
IN ULONG_PTR ResourceName,
|
||||
IN ULONG ResourceType,
|
||||
OUT PVOID* Resource,
|
||||
OUT PULONG ResourceSize)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsNullDriverUnload(
|
||||
IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
/* now call the driver */
|
||||
Status = IoCallDriver(DeviceHeader->NextDeviceObject, Irp);
|
||||
/* did the request complete yet */
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* not yet, lets wait a bit */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -189,189 +98,3 @@ KsPinDataIntersectionEx(
|
|||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI PDEVICE_OBJECT NTAPI
|
||||
KsQueryDevicePnpObject(
|
||||
IN KSDEVICE_HEADER Header)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsRecalculateStackDepth(
|
||||
IN KSDEVICE_HEADER Header,
|
||||
IN BOOLEAN ReuseStackLocation)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsSetTargetDeviceObject(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN PDEVICE_OBJECT TargetDevice OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI VOID NTAPI
|
||||
KsSetTargetState(
|
||||
IN KSOBJECT_HEADER Header,
|
||||
IN KSTARGET_STATE TargetState)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
|
||||
|
||||
IoStatusBlock->Information = Irp->IoStatus.Information;
|
||||
IoStatusBlock->Status = Irp->IoStatus.Status;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsSynchronousIoControlDevice(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN KPROCESSOR_MODE RequestorMode,
|
||||
IN ULONG IoControl,
|
||||
IN PVOID InBuffer,
|
||||
IN ULONG InSize,
|
||||
OUT PVOID OutBuffer,
|
||||
IN ULONG OutSize,
|
||||
OUT PULONG BytesReturned)
|
||||
{
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* check for valid file object */
|
||||
if (!FileObject)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* get device object to send the request to */
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
if (!DeviceObject)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
||||
/* get object header */
|
||||
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
|
||||
#if 0
|
||||
if (!ObjectHeader)
|
||||
{
|
||||
DPRINT("Expected object header\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
/* check if there is fast device io function */
|
||||
if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
|
||||
{
|
||||
IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
||||
IoStatusBlock.Information = 0;
|
||||
|
||||
/* it is send the request */
|
||||
Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
|
||||
/* check if the request was handled */
|
||||
DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
|
||||
if (Status)
|
||||
{
|
||||
/* store bytes returned */
|
||||
*BytesReturned = IoStatusBlock.Information;
|
||||
/* return status */
|
||||
return IoStatusBlock.Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* create the irp */
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
|
||||
|
||||
/* HACK */
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
IoStack->FileObject = FileObject;
|
||||
|
||||
IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
*BytesReturned = IoStatusBlock.Information;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsAcquireDeviceSecurityLock(
|
||||
IN KSDEVICE_HEADER DevHeader,
|
||||
IN BOOLEAN Exclusive)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (Exclusive)
|
||||
{
|
||||
Status = ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
NTAPI
|
||||
KsReleaseDeviceSecurityLock(
|
||||
IN KSDEVICE_HEADER DevHeader)
|
||||
{
|
||||
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
|
||||
|
||||
ExReleaseResourceLite(&Header->SecurityLock);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef PRIV_H__
|
||||
#define PRIV_H__
|
||||
|
||||
#define _KSDDK_
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <ntddk.h>
|
||||
#define NDEBUG
|
||||
|
@ -8,6 +10,8 @@
|
|||
#include <portcls.h>
|
||||
#include <ks.h>
|
||||
#include <kcom.h>
|
||||
#include <pseh/pseh2.h>
|
||||
#include <ntndk.h>
|
||||
|
||||
#include "ksfunc.h"
|
||||
#include "kstypes.h"
|
||||
|
@ -18,4 +22,22 @@
|
|||
|
||||
#define IOCTL_KS_OBJECT_CLASS CTL_CODE(FILE_DEVICE_KS, 0x7, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
|
||||
#define DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PinSet,\
|
||||
PropGeneral, PropInstances, PropIntersection)\
|
||||
DEFINE_KSPROPERTY_TABLE(PinSet) {\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral),\
|
||||
DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(PropGeneral)\
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/event.c
|
||||
* PURPOSE: KS property handling functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/* ===============================================================
|
||||
Property Functions
|
||||
*/
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI BOOLEAN NTAPI
|
||||
KsFastPropertyHandler(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PKSPROPERTY UNALIGNED Property,
|
||||
IN ULONG PropertyLength,
|
||||
IN OUT PVOID UNALIGNED Data,
|
||||
IN ULONG DataLength,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN ULONG PropertySetsCount,
|
||||
IN const KSPROPERTY_SET* PropertySet)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsPropertyHandler(
|
||||
IN PIRP Irp,
|
||||
IN ULONG PropertySetsCount,
|
||||
|
@ -35,10 +23,13 @@ KsPropertyHandler(
|
|||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsPropertyHandlerWithAllocator(
|
||||
IN PIRP Irp,
|
||||
IN ULONG PropertySetsCount,
|
||||
|
@ -53,12 +44,19 @@ KsPropertyHandlerWithAllocator(
|
|||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI NTSTATUS NTAPI
|
||||
KsUnserializeObjectPropertiesFromRegistry(
|
||||
KSDDKAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KsFastPropertyHandler(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN HANDLE ParentKey OPTIONAL,
|
||||
IN PUNICODE_STRING RegistryPath OPTIONAL)
|
||||
IN PKSPROPERTY UNALIGNED Property,
|
||||
IN ULONG PropertyLength,
|
||||
IN OUT PVOID UNALIGNED Data,
|
||||
IN ULONG DataLength,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN ULONG PropertySetsCount,
|
||||
IN const KSPROPERTY_SET* PropertySet)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
return FALSE;
|
||||
}
|
|
@ -1,8 +1,14 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/topoology.c
|
||||
* PURPOSE: KS Allocator functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/* ===============================================================
|
||||
Topology Functions
|
||||
*/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
@ -291,3 +297,14 @@ KsTopologyPropertyHandler(
|
|||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspTopologyPropertyHandler(
|
||||
IN PIRP Irp,
|
||||
IN PKSIDENTIFIER Request,
|
||||
IN OUT PVOID Data)
|
||||
{
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel Streaming
|
||||
* FILE: drivers/ksfilter/ks/worker.c
|
||||
* PURPOSE: KS Allocator functions
|
||||
* PROGRAMMER: Johannes Anderwald
|
||||
*/
|
||||
|
||||
|
||||
#include "priv.h"
|
||||
|
||||
/* ===============================================================
|
||||
|
|
Loading…
Reference in a new issue