reactos/ntoskrnl/io/iomgr/controller.c
2018-12-16 10:30:23 +01:00

152 lines
4.5 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/iomgr/controller.c
* PURPOSE: I/O Wrappers (called Controllers) for Kernel Device Queues
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#include <debug.h>
/* GLOBALS *******************************************************************/
POBJECT_TYPE IoControllerObjectType;
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
VOID
NTAPI
IoAllocateController(IN PCONTROLLER_OBJECT ControllerObject,
IN PDEVICE_OBJECT DeviceObject,
IN PDRIVER_CONTROL ExecutionRoutine,
IN PVOID Context)
{
IO_ALLOCATION_ACTION Result;
ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
/* Initialize the Wait Context Block */
DeviceObject->Queue.Wcb.DeviceContext = Context;
DeviceObject->Queue.Wcb.DeviceRoutine = ExecutionRoutine;
/* Insert the Device Queue */
if (!KeInsertDeviceQueue(&ControllerObject->DeviceWaitQueue,
&DeviceObject->Queue.Wcb.WaitQueueEntry))
{
/* Call the execution routine */
Result = ExecutionRoutine(DeviceObject,
DeviceObject->CurrentIrp,
NULL,
Context);
/* Free the controller if this was requested */
if (Result == DeallocateObject) IoFreeController(ControllerObject);
}
}
/*
* @implemented
*/
PCONTROLLER_OBJECT
NTAPI
IoCreateController(IN ULONG Size)
{
PCONTROLLER_OBJECT Controller;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Handle;
NTSTATUS Status;
PAGED_CODE();
/* Initialize an empty OBA */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
/* Create the Object */
Status = ObCreateObject(KernelMode,
IoControllerObjectType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(CONTROLLER_OBJECT) + Size,
0,
0,
(PVOID*)&Controller);
if (!NT_SUCCESS(Status)) return NULL;
/* Insert it */
Status = ObInsertObject(Controller,
NULL,
FILE_READ_DATA | FILE_WRITE_DATA,
1,
(PVOID*)&Controller,
&Handle);
if (!NT_SUCCESS(Status)) return NULL;
/* Close the dummy handle */
ObCloseHandle(Handle, KernelMode);
/* Zero the Object and set its data */
RtlZeroMemory(Controller, sizeof(CONTROLLER_OBJECT) + Size);
Controller->Type = IO_TYPE_CONTROLLER;
Controller->Size = sizeof(CONTROLLER_OBJECT) + (CSHORT)Size;
Controller->ControllerExtension = (Controller + 1);
/* Initialize its Queue */
KeInitializeDeviceQueue(&Controller->DeviceWaitQueue);
/* Return Controller */
return Controller;
}
/*
* @implemented
*/
VOID
NTAPI
IoDeleteController(IN PCONTROLLER_OBJECT ControllerObject)
{
/* Just Dereference it */
ObDereferenceObject(ControllerObject);
}
/*
* @implemented
*/
VOID
NTAPI
IoFreeController(IN PCONTROLLER_OBJECT ControllerObject)
{
PKDEVICE_QUEUE_ENTRY QueueEntry;
PDEVICE_OBJECT DeviceObject;
IO_ALLOCATION_ACTION Result;
/* Remove the Queue */
QueueEntry = KeRemoveDeviceQueue(&ControllerObject->DeviceWaitQueue);
if (QueueEntry)
{
/* Get the Device Object */
DeviceObject = CONTAINING_RECORD(QueueEntry,
DEVICE_OBJECT,
Queue.Wcb.WaitQueueEntry);
/* Call the routine */
Result = DeviceObject->Queue.Wcb.DeviceRoutine(DeviceObject,
DeviceObject->CurrentIrp,
NULL,
DeviceObject->
Queue.Wcb.DeviceContext);
/* Free the controller if this was requested */
if (Result == DeallocateObject) IoFreeController(ControllerObject);
}
}
/* EOF */