This commit was generated by cvs2svn to compensate for changes in r30,
[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 <internal/string.h>
33 #include <ddk/ntddk.h>
34
35 #define NDEBUG
36 #include <internal/debug.h>
37
38 /* FUNCTIONS ****************************************************************/
39
40 PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread)
41 /*
42 * FUNCTION: Returns a pointer to the device, representing a removable-media
43 * device, that is the target of the given thread's I/O request
44 */
45 {
46 UNIMPLEMENTED;
47 }
48
49 VOID IoFreeIrp(PIRP Irp)
50 /*
51 * FUNCTION: Releases a caller allocated irp
52 * ARGUMENTS:
53 * Irp = Irp to free
54 */
55 {
56 ExFreePool(Irp);
57 }
58
59 PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize)
60 /*
61 * FUNCTION: Allocates and initializes an irp to associated with a master irp
62 * ARGUMENTS:
63 * Irp = Master irp
64 * StackSize = Number of stack locations to be allocated in the irp
65 * RETURNS: The irp allocated
66 */
67 {
68 PIRP AssocIrp;
69
70 AssocIrp = IoAllocateIrp(StackSize,FALSE);
71 UNIMPLEMENTED;
72 }
73
74 VOID IoMarkIrpPending(PIRP Irp)
75 /*
76 * FUNCTION: Marks the specified irp, indicating further processing will
77 * be required by other driver routines
78 * ARGUMENTS:
79 * Irp = Irp to mark
80 */
81 {
82 IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
83 }
84
85 PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction,
86 PDEVICE_OBJECT DeviceObject,
87 PVOID Buffer,
88 ULONG Length,
89 PLARGE_INTEGER StartingOffset,
90 PIO_STATUS_BLOCK IoStatusBlock)
91 /*
92 * FUNCTION: Allocates and sets up an IRP to be sent to lower level drivers
93 * ARGUMENTS:
94 * MajorFunction = One of IRP_MJ_READ, IRP_MJ_WRITE,
95 * IRP_MJ_FLUSH_BUFFERS or IRP_MJ_SHUTDOWN
96 * DeviceObject = Device object to send the irp to
97 * Buffer = Buffer into which data will be read or written
98 * Length = Length in bytes of the irp to be allocated
99 * StartingOffset = Starting offset on the device
100 * IoStatusBlock (OUT) = Storage for the result of the operation
101 * RETURNS: The IRP allocated on success, or
102 * NULL on failure
103 */
104 {
105 PIRP Irp;
106 PIO_STACK_LOCATION StackPtr;
107
108 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
109 if (Irp==NULL)
110 {
111 return(NULL);
112 }
113
114 Irp->UserBuffer = (LPVOID)Buffer;
115 if (DeviceObject->Flags&DO_BUFFERED_IO)
116 {
117 DPRINT("Doing buffer i/o\n",0);
118 Irp->AssociatedIrp.SystemBuffer = (PVOID)
119 ExAllocatePool(NonPagedPool,Length);
120 if (Irp->AssociatedIrp.SystemBuffer==NULL)
121 {
122 return(NULL);
123 }
124 Irp->UserBuffer = NULL;
125 }
126 if (DeviceObject->Flags&DO_DIRECT_IO)
127 {
128 DPRINT("Doing direct i/o\n",0);
129
130 Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
131 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
132 Irp->UserBuffer = NULL;
133 Irp->AssociatedIrp.SystemBuffer = NULL;
134 }
135
136 Irp->UserIosb = IoStatusBlock;
137
138 StackPtr = IoGetNextIrpStackLocation(Irp);
139 StackPtr->MajorFunction = MajorFunction;
140 StackPtr->MinorFunction = 0;
141 StackPtr->Flags = 0;
142 StackPtr->Control = 0;
143 StackPtr->DeviceObject = DeviceObject;
144 StackPtr->FileObject = NULL;
145 StackPtr->Parameters.Write.Length = Length;
146 if (StartingOffset!=NULL)
147 {
148 StackPtr->Parameters.Write.ByteOffset.LowPart =
149 StartingOffset->LowPart;
150 StackPtr->Parameters.Write.ByteOffset.HighPart =
151 StartingOffset->HighPart;
152 }
153 else
154 {
155 StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
156 StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
157 }
158
159 return(Irp);
160 }
161
162 PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode,
163 PDEVICE_OBJECT DeviceObject,
164 PVOID InputBuffer,
165 ULONG InputBufferLength,
166 PVOID OutputBuffer,
167 ULONG OutputBufferLength,
168 BOOLEAN InternalDeviceIoControl,
169 PKEVENT Event,
170 PIO_STATUS_BLOCK IoStatusBlock)
171 {
172 UNIMPLEMENTED;
173 }
174
175 PIRP IoBuildSynchronousFsdRequest(ULONG MajorFunction,
176 PDEVICE_OBJECT DeviceObject,
177 PVOID Buffer,
178 ULONG Length,
179 PLARGE_INTEGER StartingOffset,
180 PKEVENT Event,
181 PIO_STATUS_BLOCK IoStatusBlock)
182 /*
183 * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
184 * level driver(s)
185 * ARGUMENTS:
186 * MajorFunction = Major function code, one of IRP_MJ_READ,
187 * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
188 * DeviceObject = Target device object
189 * Buffer = Buffer containing data for a read or write
190 * Length = Length in bytes of the information to be transferred
191 * StartingOffset = Offset to begin the read/write from
192 * Event (OUT) = Will be set when the operation is complete
193 * IoStatusBlock (OUT) = Set to the status of the operation
194 * RETURNS: The IRP allocated on success, or
195 * NULL on failure
196 */
197 {
198 PIRP Irp;
199 PIO_STACK_LOCATION StackPtr;
200
201 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
202 if (Irp==NULL)
203 {
204 return(NULL);
205 }
206
207 Irp->UserBuffer = (LPVOID)Buffer;
208 if (DeviceObject->Flags&DO_BUFFERED_IO)
209 {
210 DPRINT("Doing buffer i/o\n",0);
211 Irp->AssociatedIrp.SystemBuffer = (PVOID)
212 ExAllocatePool(NonPagedPool,Length);
213 if (Irp->AssociatedIrp.SystemBuffer==NULL)
214 {
215 return(NULL);
216 }
217 Irp->UserBuffer = NULL;
218 }
219 if (DeviceObject->Flags&DO_DIRECT_IO)
220 {
221 DPRINT("Doing direct i/o\n",0);
222
223 Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
224 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
225 Irp->UserBuffer = NULL;
226 Irp->AssociatedIrp.SystemBuffer = NULL;
227 }
228
229 Irp->UserIosb = IoStatusBlock;
230 Irp->UserEvent = Event;
231
232 StackPtr = IoGetNextIrpStackLocation(Irp);
233 StackPtr->MajorFunction = MajorFunction;
234 StackPtr->MinorFunction = 0;
235 StackPtr->Flags = 0;
236 StackPtr->Control = 0;
237 StackPtr->DeviceObject = DeviceObject;
238 StackPtr->FileObject = NULL;
239 StackPtr->Parameters.Write.Length = Length;
240 if (StartingOffset!=NULL)
241 {
242 StackPtr->Parameters.Write.ByteOffset.LowPart =
243 StartingOffset->LowPart;
244 StackPtr->Parameters.Write.ByteOffset.HighPart =
245 StartingOffset->HighPart;
246 }
247 else
248 {
249 StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
250 StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
251 }
252
253 return(Irp);
254 }
255
256 USHORT IoSizeOfIrp(CCHAR StackSize)
257 /*
258 * FUNCTION: Determines the size of an IRP
259 * ARGUMENTS:
260 * StackSize = number of stack locations in the IRP
261 * RETURNS: The size of the IRP in bytes
262 */
263 {
264 return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
265 }
266
267 VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize)
268 /*
269 * FUNCTION: Initalizes an irp allocated by the caller
270 * ARGUMENTS:
271 * Irp = IRP to initalize
272 * PacketSize = Size in bytes of the IRP
273 * StackSize = Number of stack locations in the IRP
274 */
275 {
276 assert(Irp!=NULL);
277 memset(Irp,0,PacketSize);
278 Irp->CurrentLocation=StackSize;
279 Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp);
280 }
281
282 PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
283 /*
284 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
285 * the given IRP
286 * ARGUMENTS:
287 * Irp = Points to the IRP
288 * RETURNS: A pointer to the stack location
289 */
290 {
291 return(&Irp->Stack[Irp->CurrentLocation]);
292 }
293
294
295 VOID IoSetNextIrpStackLocation(PIRP Irp)
296 {
297 Irp->CurrentLocation--;
298 Irp->Tail.Overlay.CurrentStackLocation--;
299 }
300
301 PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp)
302 /*
303 * FUNCTION: Gives a higher level driver access to the next lower driver's
304 * I/O stack location
305 * ARGUMENTS:
306 * Irp = points to the irp
307 * RETURNS: A pointer to the stack location
308 */
309 {
310 assert(Irp!=NULL);
311 DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
312 return(&Irp->Stack[Irp->CurrentLocation-1]);
313 }
314
315 NTSTATUS IoCallDriver(PDEVICE_OBJECT DevObject, PIRP irp)
316 /*
317 * FUNCTION: Sends an IRP to the next lower driver
318 */
319 {
320 PDRIVER_OBJECT drv = DevObject->DriverObject;
321 IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(irp);
322 DPRINT("Deviceobject %x\n",DevObject);
323 DPRINT("Irp %x\n",irp);
324 irp->Tail.Overlay.CurrentStackLocation--;
325 irp->CurrentLocation--;
326 DPRINT("Io stack address %x\n",param);
327 DPRINT("Function %d Routine %x\n",param->MajorFunction,
328 drv->MajorFunction[param->MajorFunction]);
329 DPRINT("IRP_MJ_CREATE %d\n",IRP_MJ_CREATE);
330
331 return(drv->MajorFunction[param->MajorFunction](DevObject,irp));
332 }
333
334 PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota)
335 /*
336 * FUNCTION: Allocates an IRP
337 * ARGUMENTS:
338 * StackSize = the size of the stack required for the irp
339 * ChargeQuota = Charge allocation to current threads quota
340 * RETURNS: Irp allocated
341 */
342 {
343 PIRP Irp;
344
345 DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize,
346 ChargeQuota);
347 if (ChargeQuota)
348 {
349 Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
350 }
351 else
352 {
353 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
354 }
355
356 if (Irp==NULL)
357 {
358 return(NULL);
359 }
360
361 Irp->CurrentLocation=StackSize;
362
363 DPRINT("Irp %x Irp->StackPtr %d\n",Irp,Irp->CurrentLocation);
364 return(Irp);
365 }
366
367 VOID IoSetCompletionRoutine(PIRP Irp,
368 PIO_COMPLETION_ROUTINE CompletionRoutine,
369 PVOID Context,
370 BOOLEAN InvokeOnSuccess,
371 BOOLEAN InvokeOnError,
372 BOOLEAN InvokeOnCancel)
373 {
374 IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);
375
376 param->CompletionRoutine=CompletionRoutine;
377 param->CompletionContext=Context;
378 if (InvokeOnSuccess)
379 {
380 param->Control = SL_INVOKE_ON_SUCCESS;
381 }
382 if (InvokeOnError)
383 {
384 param->Control = param->Control | SL_INVOKE_ON_ERROR;
385 }
386 if (InvokeOnCancel)
387 {
388 param->Control = param->Control | SL_INVOKE_ON_CANCEL;
389 }
390 }
391
392 VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
393 /*
394 * FUNCTION: Indicates the caller has finished all processing for a given
395 * I/O request and is returning the given IRP to the I/O manager
396 * ARGUMENTS:
397 * Irp = Irp to be cancelled
398 * PriorityBoost = Increment by which to boost the priority of the
399 * thread making the request
400 */
401 {
402 unsigned int i=0;
403 unsigned int stack_size;
404
405 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n",
406 Irp,PriorityBoost);
407 DPRINT("Irp->Stack[i].DeviceObject->StackSize %x\n",
408 Irp->Stack[i].DeviceObject->StackSize);
409 stack_size = Irp->Stack[i].DeviceObject->StackSize;
410 for (i=0;i<stack_size;i++)
411 {
412 if (Irp->Stack[i].CompletionRoutine!=NULL)
413 {
414 Irp->Stack[i].CompletionRoutine(Irp->Stack[i].DeviceObject,Irp,
415 Irp->Stack[i].CompletionContext);
416 }
417 }
418
419 if (Irp->UserEvent!=NULL)
420 {
421 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
422 }
423 if (Irp->UserIosb!=NULL)
424 {
425 *Irp->UserIosb=Irp->IoStatus;
426 }
427
428 /*
429 * If the
430 */
431 }