*** empty log message ***
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/irp.c
5 * PURPOSE: Handle IRPs
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * 24/05/98: Created
9 */
10
11 /* NOTES *******************************************************************
12 *
13 * Layout of an IRP
14 *
15 * ################
16 * # Headers #
17 * ################
18 * # #
19 * # Variable #
20 * # length list #
21 * # of io stack #
22 * # locations #
23 * # #
24 * ################
25 *
26 *
27 *
28 */
29
30 /* INCLUDES ****************************************************************/
31
32 #include <ddk/ntddk.h>
33 #include <string.h>
34 #include <internal/string.h>
35 #include <internal/io.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* FUNCTIONS ****************************************************************/
41
42 PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread)
43 /*
44 * FUNCTION: Returns a pointer to the device, representing a removable-media
45 * device, that is the target of the given thread's I/O request
46 */
47 {
48 UNIMPLEMENTED;
49 }
50
51 VOID IoFreeIrp(PIRP Irp)
52 /*
53 * FUNCTION: Releases a caller allocated irp
54 * ARGUMENTS:
55 * Irp = Irp to free
56 */
57 {
58 ExFreePool(Irp);
59 }
60
61 PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize)
62 /*
63 * FUNCTION: Allocates and initializes an irp to associated with a master irp
64 * ARGUMENTS:
65 * Irp = Master irp
66 * StackSize = Number of stack locations to be allocated in the irp
67 * RETURNS: The irp allocated
68 */
69 {
70 PIRP AssocIrp;
71
72 AssocIrp = IoAllocateIrp(StackSize,FALSE);
73 UNIMPLEMENTED;
74 }
75
76 VOID IoMarkIrpPending(PIRP Irp)
77 /*
78 * FUNCTION: Marks the specified irp, indicating further processing will
79 * be required by other driver routines
80 * ARGUMENTS:
81 * Irp = Irp to mark
82 */
83 {
84 DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
85 IoGetCurrentIrpStackLocation(Irp));
86 IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
87 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
88 DPRINT("IoGetCurrentIrpStackLocation(Irp)->Control %x\n",
89 IoGetCurrentIrpStackLocation(Irp)->Control);
90 DPRINT("SL_PENDING_RETURNED %x\n",SL_PENDING_RETURNED);
91 }
92
93 USHORT IoSizeOfIrp(CCHAR StackSize)
94 /*
95 * FUNCTION: Determines the size of an IRP
96 * ARGUMENTS:
97 * StackSize = number of stack locations in the IRP
98 * RETURNS: The size of the IRP in bytes
99 */
100 {
101 return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
102 }
103
104 VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize)
105 /*
106 * FUNCTION: Initalizes an irp allocated by the caller
107 * ARGUMENTS:
108 * Irp = IRP to initalize
109 * PacketSize = Size in bytes of the IRP
110 * StackSize = Number of stack locations in the IRP
111 */
112 {
113 assert(Irp != NULL);
114
115 memset(Irp,0,PacketSize);
116 Irp->StackCount=StackSize;
117 Irp->CurrentLocation=StackSize;
118 Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp);
119 }
120
121 PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
122 /*
123 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
124 * the given IRP
125 * ARGUMENTS:
126 * Irp = Points to the IRP
127 * RETURNS: A pointer to the stack location
128 */
129 {
130 DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
131 Irp,
132 Irp->CurrentLocation,
133 Irp->StackCount);
134
135 return &Irp->Stack[(ULONG)Irp->CurrentLocation];
136 }
137
138
139 VOID IoSetNextIrpStackLocation(PIRP Irp)
140 {
141 Irp->CurrentLocation--;
142 Irp->Tail.Overlay.CurrentStackLocation--;
143 }
144
145 PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp)
146 /*
147 * FUNCTION: Gives a higher level driver access to the next lower driver's
148 * I/O stack location
149 * ARGUMENTS:
150 * Irp = points to the irp
151 * RETURNS: A pointer to the stack location
152 */
153 {
154 DPRINT("IoGetNextIrpStackLocation(Irp %x)\n",Irp);
155
156 assert(Irp!=NULL);
157 DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
158 return(&Irp->Stack[Irp->CurrentLocation-1]);
159 }
160
161 NTSTATUS IoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp)
162 /*
163 * FUNCTION: Sends an IRP to the next lower driver
164 */
165 {
166 NTSTATUS Status;
167 PDRIVER_OBJECT DriverObject;
168 PIO_STACK_LOCATION param;
169
170 DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
171
172 DriverObject = DeviceObject->DriverObject;
173 param = IoGetNextIrpStackLocation(Irp);
174
175 Irp->Tail.Overlay.CurrentStackLocation--;
176 Irp->CurrentLocation--;
177
178 DPRINT("MajorFunction %d\n",MajorFunction);
179 DPRINT("DriverObject->MajorFunction[param->MajorFunction] %x\n",
180 DriverObject->MajorFunction[param->MajorFunction]);
181 Status = DriverObject->MajorFunction[param->MajorFunction](DeviceObject,
182 Irp);
183 return Status;
184 }
185
186 PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota)
187 /*
188 * FUNCTION: Allocates an IRP
189 * ARGUMENTS:
190 * StackSize = the size of the stack required for the irp
191 * ChargeQuota = Charge allocation to current threads quota
192 * RETURNS: Irp allocated
193 */
194 {
195 PIRP Irp;
196
197 #if 0
198 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
199 StackSize,
200 ChargeQuota);
201 KeDumpStackFrames(0,8);
202 #endif
203
204 if (ChargeQuota)
205 {
206 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
207 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
208 }
209 else
210 {
211 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
212 }
213
214 if (Irp==NULL)
215 {
216 return(NULL);
217 }
218
219 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
220
221 DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
222
223 return Irp;
224 }
225
226 VOID IoSetCompletionRoutine(PIRP Irp,
227 PIO_COMPLETION_ROUTINE CompletionRoutine,
228 PVOID Context,
229 BOOLEAN InvokeOnSuccess,
230 BOOLEAN InvokeOnError,
231 BOOLEAN InvokeOnCancel)
232 {
233 IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);
234
235 param->CompletionRoutine=CompletionRoutine;
236 param->CompletionContext=Context;
237 if (InvokeOnSuccess)
238 {
239 param->Control = param->Control | SL_INVOKE_ON_SUCCESS;
240 }
241 if (InvokeOnError)
242 {
243 param->Control = param->Control | SL_INVOKE_ON_ERROR;
244 }
245 if (InvokeOnCancel)
246 {
247 param->Control = param->Control | SL_INVOKE_ON_CANCEL;
248 }
249 }
250
251 VOID IopCompleteRequest(struct _KAPC* Apc,
252 PKNORMAL_ROUTINE* NormalRoutine,
253 PVOID* NormalContext,
254 PVOID* SystemArgument1,
255 PVOID* SystemArgument2)
256 {
257 IoSecondStageCompletion((PIRP)(*NormalContext),
258 IO_NO_INCREMENT);
259 }
260
261 VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
262 /*
263 * FUNCTION: Indicates the caller has finished all processing for a given
264 * I/O request and is returning the given IRP to the I/O manager
265 * ARGUMENTS:
266 * Irp = Irp to be cancelled
267 * PriorityBoost = Increment by which to boost the priority of the
268 * thread making the request
269 */
270 {
271 unsigned int i;
272 NTSTATUS Status;
273
274 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n",
275 Irp,PriorityBoost);
276
277 for (i=0;i<Irp->StackCount;i++)
278 {
279 if (Irp->Stack[i].CompletionRoutine != NULL)
280 {
281 Status = Irp->Stack[i].CompletionRoutine(
282 Irp->Stack[i].DeviceObject,
283 Irp,
284 Irp->Stack[i].CompletionContext);
285 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
286 {
287 return;
288 }
289 }
290 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
291 {
292 Irp->PendingReturned = TRUE;
293 }
294 }
295
296 if (Irp->PendingReturned)
297 {
298 KeInitializeApc(&Irp->Tail.Apc,
299 &Irp->Tail.Overlay.Thread->Tcb,
300 0,
301 IopCompleteRequest,
302 NULL,
303 NULL,
304 0,
305 Irp);
306 KeInsertQueueApc(&Irp->Tail.Apc,NULL,NULL,0);
307 }
308 else
309 {
310 IoSecondStageCompletion(Irp,PriorityBoost);
311 }
312 }
313