/* * 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 #include /* 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 */