2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/irp.c
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* NOTES *******************************************************************
30 /* INCLUDES ****************************************************************/
32 #include <internal/string.h>
33 #include <ddk/ntddk.h>
36 #include <internal/debug.h>
38 /* FUNCTIONS ****************************************************************/
40 PDEVICE_OBJECT
IoGetDeviceToVerify(PETHREAD Thread
)
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
49 VOID
IoFreeIrp(PIRP Irp
)
51 * FUNCTION: Releases a caller allocated irp
59 PIRP
IoMakeAssociatedIrp(PIRP Irp
, CCHAR StackSize
)
61 * FUNCTION: Allocates and initializes an irp to associated with a master irp
64 * StackSize = Number of stack locations to be allocated in the irp
65 * RETURNS: The irp allocated
70 AssocIrp
= IoAllocateIrp(StackSize
,FALSE
);
74 VOID
IoMarkIrpPending(PIRP Irp
)
76 * FUNCTION: Marks the specified irp, indicating further processing will
77 * be required by other driver routines
82 IoGetCurrentIrpStackLocation(Irp
)->Control
|= SL_PENDING_RETURNED
;
85 PIRP
IoBuildAsynchronousFsdRequest(ULONG MajorFunction
,
86 PDEVICE_OBJECT DeviceObject
,
89 PLARGE_INTEGER StartingOffset
,
90 PIO_STATUS_BLOCK IoStatusBlock
)
92 * FUNCTION: Allocates and sets up an IRP to be sent to lower level drivers
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
106 PIO_STACK_LOCATION StackPtr
;
108 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,TRUE
);
114 Irp
->UserBuffer
= (LPVOID
)Buffer
;
115 if (DeviceObject
->Flags
&DO_BUFFERED_IO
)
117 DPRINT("Doing buffer i/o\n",0);
118 Irp
->AssociatedIrp
.SystemBuffer
= (PVOID
)
119 ExAllocatePool(NonPagedPool
,Length
);
120 if (Irp
->AssociatedIrp
.SystemBuffer
==NULL
)
124 Irp
->UserBuffer
= NULL
;
126 if (DeviceObject
->Flags
&DO_DIRECT_IO
)
128 DPRINT("Doing direct i/o\n",0);
130 Irp
->MdlAddress
= MmCreateMdl(NULL
,Buffer
,Length
);
131 MmProbeAndLockPages(Irp
->MdlAddress
,UserMode
,IoWriteAccess
);
132 Irp
->UserBuffer
= NULL
;
133 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
136 Irp
->UserIosb
= IoStatusBlock
;
138 StackPtr
= IoGetNextIrpStackLocation(Irp
);
139 StackPtr
->MajorFunction
= MajorFunction
;
140 StackPtr
->MinorFunction
= 0;
142 StackPtr
->Control
= 0;
143 StackPtr
->DeviceObject
= DeviceObject
;
144 StackPtr
->FileObject
= NULL
;
145 StackPtr
->Parameters
.Write
.Length
= Length
;
146 if (StartingOffset
!=NULL
)
148 StackPtr
->Parameters
.Write
.ByteOffset
.LowPart
=
149 StartingOffset
->LowPart
;
150 StackPtr
->Parameters
.Write
.ByteOffset
.HighPart
=
151 StartingOffset
->HighPart
;
155 StackPtr
->Parameters
.Write
.ByteOffset
.LowPart
= 0;
156 StackPtr
->Parameters
.Write
.ByteOffset
.HighPart
= 0;
162 PIRP
IoBuildDeviceIoControlRequest(ULONG IoControlCode
,
163 PDEVICE_OBJECT DeviceObject
,
165 ULONG InputBufferLength
,
167 ULONG OutputBufferLength
,
168 BOOLEAN InternalDeviceIoControl
,
170 PIO_STATUS_BLOCK IoStatusBlock
)
175 PIRP
IoBuildSynchronousFsdRequest(ULONG MajorFunction
,
176 PDEVICE_OBJECT DeviceObject
,
179 PLARGE_INTEGER StartingOffset
,
181 PIO_STATUS_BLOCK IoStatusBlock
)
183 * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
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
199 PIO_STACK_LOCATION StackPtr
;
201 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,TRUE
);
207 Irp
->UserBuffer
= (LPVOID
)Buffer
;
208 if (DeviceObject
->Flags
&DO_BUFFERED_IO
)
210 DPRINT("Doing buffer i/o\n",0);
211 Irp
->AssociatedIrp
.SystemBuffer
= (PVOID
)
212 ExAllocatePool(NonPagedPool
,Length
);
213 if (Irp
->AssociatedIrp
.SystemBuffer
==NULL
)
217 Irp
->UserBuffer
= NULL
;
219 if (DeviceObject
->Flags
&DO_DIRECT_IO
)
221 DPRINT("Doing direct i/o\n",0);
223 Irp
->MdlAddress
= MmCreateMdl(NULL
,Buffer
,Length
);
224 MmProbeAndLockPages(Irp
->MdlAddress
,UserMode
,IoWriteAccess
);
225 Irp
->UserBuffer
= NULL
;
226 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
229 Irp
->UserIosb
= IoStatusBlock
;
230 Irp
->UserEvent
= Event
;
232 StackPtr
= IoGetNextIrpStackLocation(Irp
);
233 StackPtr
->MajorFunction
= MajorFunction
;
234 StackPtr
->MinorFunction
= 0;
236 StackPtr
->Control
= 0;
237 StackPtr
->DeviceObject
= DeviceObject
;
238 StackPtr
->FileObject
= NULL
;
239 StackPtr
->Parameters
.Write
.Length
= Length
;
240 if (StartingOffset
!=NULL
)
242 StackPtr
->Parameters
.Write
.ByteOffset
.LowPart
=
243 StartingOffset
->LowPart
;
244 StackPtr
->Parameters
.Write
.ByteOffset
.HighPart
=
245 StartingOffset
->HighPart
;
249 StackPtr
->Parameters
.Write
.ByteOffset
.LowPart
= 0;
250 StackPtr
->Parameters
.Write
.ByteOffset
.HighPart
= 0;
256 USHORT
IoSizeOfIrp(CCHAR StackSize
)
258 * FUNCTION: Determines the size of an IRP
260 * StackSize = number of stack locations in the IRP
261 * RETURNS: The size of the IRP in bytes
264 return(sizeof(IRP
)+((StackSize
-1)*sizeof(IO_STACK_LOCATION
)));
267 VOID
IoInitializeIrp(PIRP Irp
, USHORT PacketSize
, CCHAR StackSize
)
269 * FUNCTION: Initalizes an irp allocated by the caller
271 * Irp = IRP to initalize
272 * PacketSize = Size in bytes of the IRP
273 * StackSize = Number of stack locations in the IRP
277 memset(Irp
,0,PacketSize
);
278 Irp
->CurrentLocation
=StackSize
;
279 Irp
->Tail
.Overlay
.CurrentStackLocation
=IoGetCurrentIrpStackLocation(Irp
);
282 PIO_STACK_LOCATION
IoGetCurrentIrpStackLocation(PIRP Irp
)
284 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
287 * Irp = Points to the IRP
288 * RETURNS: A pointer to the stack location
291 return(&Irp
->Stack
[Irp
->CurrentLocation
]);
295 VOID
IoSetNextIrpStackLocation(PIRP Irp
)
297 Irp
->CurrentLocation
--;
298 Irp
->Tail
.Overlay
.CurrentStackLocation
--;
301 PIO_STACK_LOCATION
IoGetNextIrpStackLocation(PIRP Irp
)
303 * FUNCTION: Gives a higher level driver access to the next lower driver's
306 * Irp = points to the irp
307 * RETURNS: A pointer to the stack location
311 DPRINT("Irp %x Irp->StackPtr %x\n",Irp
,Irp
->CurrentLocation
);
312 return(&Irp
->Stack
[Irp
->CurrentLocation
-1]);
315 NTSTATUS
IoCallDriver(PDEVICE_OBJECT DevObject
, PIRP irp
)
317 * FUNCTION: Sends an IRP to the next lower driver
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
);
331 return(drv
->MajorFunction
[param
->MajorFunction
](DevObject
,irp
));
334 PIRP
IoAllocateIrp(CCHAR StackSize
, BOOLEAN ChargeQuota
)
336 * FUNCTION: Allocates an IRP
338 * StackSize = the size of the stack required for the irp
339 * ChargeQuota = Charge allocation to current threads quota
340 * RETURNS: Irp allocated
345 DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize
,
349 Irp
= ExAllocatePoolWithQuota(NonPagedPool
,IoSizeOfIrp(StackSize
));
353 Irp
= ExAllocatePool(NonPagedPool
,IoSizeOfIrp(StackSize
));
361 Irp
->CurrentLocation
=StackSize
;
363 DPRINT("Irp %x Irp->StackPtr %d\n",Irp
,Irp
->CurrentLocation
);
367 VOID
IoSetCompletionRoutine(PIRP Irp
,
368 PIO_COMPLETION_ROUTINE CompletionRoutine
,
370 BOOLEAN InvokeOnSuccess
,
371 BOOLEAN InvokeOnError
,
372 BOOLEAN InvokeOnCancel
)
374 IO_STACK_LOCATION
* param
= IoGetNextIrpStackLocation(Irp
);
376 param
->CompletionRoutine
=CompletionRoutine
;
377 param
->CompletionContext
=Context
;
380 param
->Control
= SL_INVOKE_ON_SUCCESS
;
384 param
->Control
= param
->Control
| SL_INVOKE_ON_ERROR
;
388 param
->Control
= param
->Control
| SL_INVOKE_ON_CANCEL
;
392 VOID
IoCompleteRequest(PIRP Irp
, CCHAR PriorityBoost
)
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
397 * Irp = Irp to be cancelled
398 * PriorityBoost = Increment by which to boost the priority of the
399 * thread making the request
403 unsigned int stack_size
;
405 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n",
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
++)
412 if (Irp
->Stack
[i
].CompletionRoutine
!=NULL
)
414 Irp
->Stack
[i
].CompletionRoutine(Irp
->Stack
[i
].DeviceObject
,Irp
,
415 Irp
->Stack
[i
].CompletionContext
);
419 if (Irp
->UserEvent
!=NULL
)
421 KeSetEvent(Irp
->UserEvent
,PriorityBoost
,FALSE
);
423 if (Irp
->UserIosb
!=NULL
)
425 *Irp
->UserIosb
=Irp
->IoStatus
;