xref: /reactos/ntoskrnl/io/iomgr/controller.c (revision c2c66aff)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/io/iomgr/controller.c
5  * PURPOSE:         I/O Wrappers (called Controllers) for Kernel Device Queues
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <ntoskrnl.h>
12 #include <debug.h>
13 
14 /* GLOBALS *******************************************************************/
15 
16 POBJECT_TYPE IoControllerObjectType;
17 
18 /* FUNCTIONS *****************************************************************/
19 
20 /*
21  * @implemented
22  */
23 VOID
24 NTAPI
25 IoAllocateController(IN PCONTROLLER_OBJECT ControllerObject,
26                      IN PDEVICE_OBJECT DeviceObject,
27                      IN PDRIVER_CONTROL ExecutionRoutine,
28                      IN PVOID Context)
29 {
30     IO_ALLOCATION_ACTION Result;
31     ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
32 
33     /* Initialize the Wait Context Block */
34     DeviceObject->Queue.Wcb.DeviceContext = Context;
35     DeviceObject->Queue.Wcb.DeviceRoutine = ExecutionRoutine;
36 
37     /* Insert the Device Queue */
38     if (!KeInsertDeviceQueue(&ControllerObject->DeviceWaitQueue,
39                              &DeviceObject->Queue.Wcb.WaitQueueEntry))
40     {
41         /* Call the execution routine */
42         Result = ExecutionRoutine(DeviceObject,
43                                   DeviceObject->CurrentIrp,
44                                   NULL,
45                                   Context);
46 
47         /* Free the controller if this was requested */
48         if (Result == DeallocateObject) IoFreeController(ControllerObject);
49     }
50 }
51 
52 /*
53  * @implemented
54  */
55 PCONTROLLER_OBJECT
56 NTAPI
57 IoCreateController(IN ULONG Size)
58 {
59    PCONTROLLER_OBJECT Controller;
60    OBJECT_ATTRIBUTES ObjectAttributes;
61    HANDLE Handle;
62    NTSTATUS Status;
63    PAGED_CODE();
64 
65    /* Initialize an empty OBA */
66    InitializeObjectAttributes(&ObjectAttributes,
67                               NULL,
68                               OBJ_KERNEL_HANDLE,
69                               NULL,
70                               NULL);
71 
72    /* Create the Object */
73    Status = ObCreateObject(KernelMode,
74                            IoControllerObjectType,
75                            &ObjectAttributes,
76                            KernelMode,
77                            NULL,
78                            sizeof(CONTROLLER_OBJECT) + Size,
79                            0,
80                            0,
81                            (PVOID*)&Controller);
82     if (!NT_SUCCESS(Status)) return NULL;
83 
84     /* Insert it */
85     Status = ObInsertObject(Controller,
86                             NULL,
87                             FILE_READ_DATA | FILE_WRITE_DATA,
88                             1,
89                             (PVOID*)&Controller,
90                             &Handle);
91    if (!NT_SUCCESS(Status)) return NULL;
92 
93     /* Close the dummy handle */
94     ObCloseHandle(Handle, KernelMode);
95 
96     /* Zero the Object and set its data */
97     RtlZeroMemory(Controller, sizeof(CONTROLLER_OBJECT) + Size);
98     Controller->Type = IO_TYPE_CONTROLLER;
99     Controller->Size = sizeof(CONTROLLER_OBJECT) + (CSHORT)Size;
100     Controller->ControllerExtension = (Controller + 1);
101 
102     /* Initialize its Queue */
103     KeInitializeDeviceQueue(&Controller->DeviceWaitQueue);
104 
105     /* Return Controller */
106     return Controller;
107 }
108 
109 /*
110  * @implemented
111  */
112 VOID
113 NTAPI
114 IoDeleteController(IN PCONTROLLER_OBJECT ControllerObject)
115 {
116     /* Just Dereference it */
117     ObDereferenceObject(ControllerObject);
118 }
119 
120 /*
121  * @implemented
122  */
123 VOID
124 NTAPI
125 IoFreeController(IN PCONTROLLER_OBJECT ControllerObject)
126 {
127     PKDEVICE_QUEUE_ENTRY QueueEntry;
128     PDEVICE_OBJECT DeviceObject;
129     IO_ALLOCATION_ACTION Result;
130 
131     /* Remove the Queue */
132     QueueEntry = KeRemoveDeviceQueue(&ControllerObject->DeviceWaitQueue);
133     if (QueueEntry)
134     {
135         /* Get the Device Object */
136         DeviceObject = CONTAINING_RECORD(QueueEntry,
137                                          DEVICE_OBJECT,
138                                          Queue.Wcb.WaitQueueEntry);
139 
140         /* Call the routine */
141         Result = DeviceObject->Queue.Wcb.DeviceRoutine(DeviceObject,
142                                                        DeviceObject->CurrentIrp,
143                                                        NULL,
144                                                        DeviceObject->
145                                                        Queue.Wcb.DeviceContext);
146         /* Free the controller if this was requested */
147         if (Result == DeallocateObject) IoFreeController(ControllerObject);
148     }
149 }
150 
151 /* EOF */
152